summaryrefslogtreecommitdiff
path: root/sql/sql_cache.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/sql_cache.cc')
-rw-r--r--sql/sql_cache.cc428
1 files changed, 305 insertions, 123 deletions
diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc
index fc03e03dee7..f8f7bde3a62 100644
--- a/sql/sql_cache.cc
+++ b/sql/sql_cache.cc
@@ -278,7 +278,6 @@ TODO list:
- Move MRG_MYISAM table type processing to handlers, something like:
tables_used->table->file->register_used_filenames(callback,
first_argument);
- - Make derived tables cachable.
- QC improvement suggested by Monty:
- Add a counter in open_table() for how many MERGE (ISAM or MyISAM)
tables are cached in the table cache.
@@ -311,7 +310,7 @@ TODO list:
#include "emb_qcache.h"
#endif
-#if defined(EXTRA_DEBUG) && !defined(DBUG_OFF)
+#if !defined(EXTRA_DBUG) && !defined(DBUG_OFF)
#define MUTEX_LOCK(M) { DBUG_PRINT("lock", ("mutex lock 0x%lx", (ulong)(M))); \
pthread_mutex_lock(M);}
#define MUTEX_UNLOCK(M) {DBUG_PRINT("lock", ("mutex unlock 0x%lx",\
@@ -615,6 +614,7 @@ void query_cache_insert(NET *net, const char *packet, ulong length)
DBUG_VOID_RETURN;
}
header->result(result);
+ header->last_pkt_nr= net->pkt_nr;
BLOCK_UNLOCK_WR(query_block);
}
else
@@ -796,10 +796,12 @@ void Query_cache::store_query(THD *thd, TABLE_LIST *tables_used)
Query_cache_query_flags flags;
// fill all gaps between fields with 0 to get repeatable key
bzero(&flags, QUERY_CACHE_FLAGS_SIZE);
- flags.client_long_flag= (thd->client_capabilities & CLIENT_LONG_FLAG ?
- 1 : 0);
- flags.client_protocol_41= (thd->client_capabilities & CLIENT_PROTOCOL_41 ?
- 1 : 0);
+ flags.client_long_flag= test(thd->client_capabilities & CLIENT_LONG_FLAG);
+ flags.client_protocol_41= test(thd->client_capabilities &
+ CLIENT_PROTOCOL_41);
+ flags.more_results_exists= test(thd->server_status &
+ SERVER_MORE_RESULTS_EXISTS);
+ flags.pkt_nr= net->pkt_nr;
flags.character_set_client_num=
thd->variables.character_set_client->number;
flags.character_set_results_num=
@@ -812,8 +814,28 @@ void Query_cache::store_query(THD *thd, TABLE_LIST *tables_used)
flags.time_zone= thd->variables.time_zone;
flags.sql_mode= thd->variables.sql_mode;
flags.max_sort_length= thd->variables.max_sort_length;
+ flags.lc_time_names= thd->variables.lc_time_names;
flags.group_concat_max_len= thd->variables.group_concat_max_len;
- flags.lc_time_names= thd->variables.lc_time_names;
+ DBUG_PRINT("qcache", ("long %d, 4.1: %d, more results %d, pkt_nr: %d, \
+CS client: %u, CS result: %u, CS conn: %u, limit: %lu, TZ: 0x%lx, \
+sql mode: 0x%lx, sort len: %lu, conncat len: %lu",
+ (int)flags.client_long_flag,
+ (int)flags.client_protocol_41,
+ (int)flags.more_results_exists,
+ flags.pkt_nr,
+ flags.character_set_client_num,
+ flags.character_set_results_num,
+ flags.collation_connection_num,
+ flags.limit,
+ (ulong)flags.time_zone,
+ flags.sql_mode,
+ flags.max_sort_length,
+ flags.group_concat_max_len));
+ /*
+ Make InnoDB to release the adaptive hash index latch before
+ acquiring the query cache mutex.
+ */
+ ha_release_temporary_latches(thd);
STRUCT_LOCK(&structure_guard_mutex);
if (query_cache_size == 0)
@@ -931,17 +953,21 @@ end:
0 The query was cached and user was sent the result.
-1 The query was cached but we didn't have rights to use it.
No error is sent to the client yet.
+
+ NOTE
+ This method requires that sql points to allocated memory of size:
+ tot_length= query_length + thd->db_length + 1 + QUERY_CACHE_FLAGS_SIZE;
*/
int
Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length)
{
+ ulonglong engine_data;
Query_cache_query *query;
Query_cache_block *first_result_block, *result_block;
Query_cache_block_table *block_table, *block_table_end;
ulong tot_length;
Query_cache_query_flags flags;
- bool check_tables;
DBUG_ENTER("Query_cache::send_result_to_client");
if (query_cache_size == 0 || thd->locked_tables ||
@@ -969,10 +995,15 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length)
/*
Test if the query is a SELECT
(pre-space is removed in dispatch_command)
+
+ First '/' looks like comment before command it is not
+ frequently appeared in real lihe, consequently we can
+ check all such queries, too.
*/
- if (my_toupper(system_charset_info, sql[i]) != 'S' ||
- my_toupper(system_charset_info, sql[i + 1]) != 'E' ||
- my_toupper(system_charset_info, sql[i + 2]) != 'L')
+ if ((my_toupper(system_charset_info, sql[i]) != 'S' ||
+ my_toupper(system_charset_info, sql[i + 1]) != 'E' ||
+ my_toupper(system_charset_info, sql[i + 2]) != 'L') &&
+ sql[i] != '/')
{
DBUG_PRINT("qcache", ("The statement is not a SELECT; Not cached"));
goto err;
@@ -1001,10 +1032,12 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length)
// fill all gaps between fields with 0 to get repeatable key
bzero(&flags, QUERY_CACHE_FLAGS_SIZE);
- flags.client_long_flag= (thd->client_capabilities & CLIENT_LONG_FLAG ?
- 1 : 0);
- flags.client_protocol_41= (thd->client_capabilities & CLIENT_PROTOCOL_41 ?
- 1 : 0);
+ flags.client_long_flag= test(thd->client_capabilities & CLIENT_LONG_FLAG);
+ flags.client_protocol_41= test(thd->client_capabilities &
+ CLIENT_PROTOCOL_41);
+ flags.more_results_exists= test(thd->server_status &
+ SERVER_MORE_RESULTS_EXISTS);
+ flags.pkt_nr= thd->net.pkt_nr;
flags.character_set_client_num= thd->variables.character_set_client->number;
flags.character_set_results_num=
(thd->variables.character_set_results ?
@@ -1016,7 +1049,22 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length)
flags.sql_mode= thd->variables.sql_mode;
flags.max_sort_length= thd->variables.max_sort_length;
flags.group_concat_max_len= thd->variables.group_concat_max_len;
- flags.lc_time_names= thd->variables.lc_time_names;
+ flags.lc_time_names= thd->variables.lc_time_names;
+ DBUG_PRINT("qcache", ("long %d, 4.1: %d, more results %d, pkt_nr: %d, \
+CS client: %u, CS result: %u, CS conn: %u, limit: %lu, TZ: 0x%lx, \
+sql mode: 0x%lx, sort len: %lu, conncat len: %lu",
+ (int)flags.client_long_flag,
+ (int)flags.client_protocol_41,
+ (int)flags.more_results_exists,
+ flags.pkt_nr,
+ flags.character_set_client_num,
+ flags.character_set_results_num,
+ flags.collation_connection_num,
+ flags.limit,
+ (ulong)flags.time_zone,
+ flags.sql_mode,
+ flags.max_sort_length,
+ flags.group_concat_max_len));
memcpy((void *)(sql + (tot_length - QUERY_CACHE_FLAGS_SIZE)),
&flags, QUERY_CACHE_FLAGS_SIZE);
query_block = (Query_cache_block *) hash_search(&queries, (byte*) sql,
@@ -1055,7 +1103,6 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length)
goto err_unlock;
}
- check_tables= query->tables_type() & HA_CACHE_TBL_ASKTRANSACT;
// Check access;
block_table= query_block->table(0);
block_table_end= block_table+query_block->n_tables;
@@ -1063,7 +1110,6 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length)
{
TABLE_LIST table_list;
TABLE *tmptable;
-
Query_cache_table *table = block_table->parent;
/*
@@ -1074,8 +1120,9 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length)
*/
for (tmptable= thd->temporary_tables; tmptable ; tmptable= tmptable->next)
{
- if (tmptable->key_length - TMP_TABLE_KEY_EXTRA == table->key_length() &&
- !memcmp(tmptable->table_cache_key, table->data(),
+ if (tmptable->s->key_length - TMP_TABLE_KEY_EXTRA ==
+ table->key_length() &&
+ !memcmp(tmptable->s->table_cache_key, table->data(),
table->key_length()))
{
DBUG_PRINT("qcache",
@@ -1095,7 +1142,7 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length)
bzero((char*) &table_list,sizeof(table_list));
table_list.db = table->db();
- table_list.alias= table_list.real_name= table->table();
+ table_list.alias= table_list.table_name= table->table();
#ifndef NO_EMBEDDED_ACCESS_CHECKS
if (check_table_access(thd,SELECT_ACL,&table_list,1))
{
@@ -1116,19 +1163,30 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length)
goto err_unlock; // Parse query
}
#endif /*!NO_EMBEDDED_ACCESS_CHECKS*/
- if (check_tables && !ha_caching_allowed(thd, table->db(),
- table->key_length(),
- table->type()))
+ engine_data= table->engine_data();
+ if (table->callback() &&
+ !(*table->callback())(thd, table->db(),
+ table->key_length(),
+ &engine_data))
{
DBUG_PRINT("qcache", ("Handler does not allow caching for %s.%s",
table_list.db, table_list.alias));
BLOCK_UNLOCK_RD(query_block);
- thd->lex->safe_to_cache_query= 0; // Don't try to cache this
+ if (engine_data != table->engine_data())
+ {
+ DBUG_PRINT("qcache",
+ ("Handler require invalidation queries of %s.%s %lld-%lld",
+ table_list.db, table_list.alias,
+ engine_data, table->engine_data()));
+ invalidate_table((byte *) table->db(), table->key_length());
+ }
+ else
+ thd->lex->safe_to_cache_query= 0; // Don't try to cache this
goto err_unlock; // Parse query
}
else
- DBUG_PRINT("qcache", ("handler allow caching (%d) %s,%s",
- check_tables, table_list.db, table_list.alias));
+ DBUG_PRINT("qcache", ("handler allow caching %s,%s",
+ table_list.db, table_list.alias));
}
move_to_query_list_end(query_block);
hits++;
@@ -1152,6 +1210,7 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length)
ALIGN_SIZE(sizeof(Query_cache_result))))
break; // Client aborted
result_block = result_block->next;
+ thd->net.pkt_nr= query->last_pkt_nr; // Keep packet number updated
} while (result_block != first_result_block);
#else
{
@@ -1162,6 +1221,7 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length)
#endif /*!EMBEDDED_LIBRARY*/
thd->limit_found_rows = query->found_rows();
+ thd->status_var.last_query_cost= 0.0;
BLOCK_UNLOCK_RD(query_block);
DBUG_RETURN(1); // Result sent to client
@@ -1190,7 +1250,7 @@ void Query_cache::invalidate(THD *thd, TABLE_LIST *tables_used,
using_transactions = using_transactions &&
(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN));
- for (; tables_used; tables_used=tables_used->next)
+ for (; tables_used; tables_used= tables_used->next_local)
{
DBUG_ASSERT(!using_transactions || tables_used->table!=0);
if (tables_used->derived)
@@ -1222,7 +1282,7 @@ void Query_cache::invalidate(CHANGED_TABLE_LIST *tables_used)
if (query_cache_size > 0)
{
DUMP(this);
- for (; tables_used; tables_used=tables_used->next)
+ for (; tables_used; tables_used= tables_used->next)
{
invalidate_table((byte*) tables_used->key, tables_used->key_length);
DBUG_PRINT("qcache", (" db %s, table %s", tables_used->key,
@@ -1255,9 +1315,10 @@ void Query_cache::invalidate_locked_for_write(TABLE_LIST *tables_used)
if (query_cache_size > 0)
{
DUMP(this);
- for (; tables_used; tables_used= tables_used->next)
+ for (; tables_used; tables_used= tables_used->next_local)
{
- if (tables_used->lock_type & (TL_WRITE_LOW_PRIORITY | TL_WRITE))
+ if (tables_used->lock_type & (TL_WRITE_LOW_PRIORITY | TL_WRITE) &&
+ tables_used->table)
invalidate_table(tables_used->table);
}
}
@@ -2057,7 +2118,7 @@ my_bool Query_cache::allocate_data_chain(Query_cache_block **result_block,
*/
data_len= len - new_block->length;
prev_block= new_block;
- } while(1);
+ } while (1);
DBUG_RETURN(TRUE);
}
@@ -2080,7 +2141,7 @@ void Query_cache::invalidate_table(TABLE_LIST *table_list)
uint key_length;
Query_cache_block *table_block;
key_length=(uint) (strmov(strmov(key,table_list->db)+1,
- table_list->real_name) -key)+ 1;
+ table_list->table_name) -key)+ 1;
// We don't store temporary tables => no key_length+=4 ...
if ((table_block = (Query_cache_block*)
@@ -2091,7 +2152,7 @@ void Query_cache::invalidate_table(TABLE_LIST *table_list)
void Query_cache::invalidate_table(TABLE *table)
{
- invalidate_table((byte*) table->table_cache_key, table->key_length);
+ invalidate_table((byte*) table->s->table_cache_key, table->s->key_length);
}
void Query_cache::invalidate_table(byte * key, uint32 key_length)
@@ -2113,6 +2174,107 @@ void Query_cache::invalidate_table(Query_cache_block *table_block)
}
}
+
+/*
+ Register given table list begining with given position in tables table of
+ block
+
+ SYNOPSIS
+ Query_cache::register_tables_from_list
+ tables_used given table list
+ counter number current position in table of tables of block
+ block_table pointer to current position in tables table of block
+
+ RETURN
+ 0 error
+ number of next position of table entry in table of tables of block
+*/
+
+TABLE_COUNTER_TYPE
+Query_cache::register_tables_from_list(TABLE_LIST *tables_used,
+ TABLE_COUNTER_TYPE counter,
+ Query_cache_block_table *block_table)
+{
+ TABLE_COUNTER_TYPE n;
+ DBUG_ENTER("Query_cache::register_tables_from_list");
+ for (n= counter;
+ tables_used;
+ tables_used= tables_used->next_global, n++, block_table++)
+ {
+ if (tables_used->derived && !tables_used->view)
+ {
+ DBUG_PRINT("qcache", ("derived table skipped"));
+ n--;
+ block_table--;
+ continue;
+ }
+ block_table->n= n;
+ if (tables_used->view)
+ {
+ char key[MAX_DBKEY_LENGTH];
+ uint key_length;
+ DBUG_PRINT("qcache", ("view %s, db %s",
+ tables_used->view_name.str,
+ tables_used->view_db.str));
+ key_length= (uint) (strmov(strmov(key, tables_used->view_db.str) + 1,
+ tables_used->view_name.str) - key) + 1;
+ /*
+ There are not callback function for for VIEWs
+ */
+ if (!insert_table(key_length, key, block_table,
+ tables_used->view_db.length + 1,
+ HA_CACHE_TBL_NONTRANSACT, 0, 0))
+ DBUG_RETURN(0);
+ /*
+ We do not need to register view tables here because they are already
+ present in the global list.
+ */
+ }
+ else
+ {
+ DBUG_PRINT("qcache",
+ ("table %s, db %s, openinfo at 0x%lx, keylen %u, key at 0x%lx",
+ tables_used->table->s->table_name,
+ tables_used->table->s->table_cache_key,
+ (ulong) tables_used->table,
+ tables_used->table->s->key_length,
+ (ulong) tables_used->table->s->table_cache_key));
+ if (!insert_table(tables_used->table->s->key_length,
+ tables_used->table->s->table_cache_key, block_table,
+ tables_used->db_length,
+ tables_used->table->file->table_cache_type(),
+ tables_used->callback_func,
+ tables_used->engine_data))
+ DBUG_RETURN(0);
+
+ if (tables_used->table->s->db_type == DB_TYPE_MRG_MYISAM)
+ {
+ ha_myisammrg *handler = (ha_myisammrg *) tables_used->table->file;
+ MYRG_INFO *file = handler->myrg_info();
+ for (MYRG_TABLE *table = file->open_tables;
+ table != file->end_table ;
+ table++)
+ {
+ char key[MAX_DBKEY_LENGTH];
+ uint32 db_length;
+ uint key_length= filename_2_table_key(key, table->table->filename,
+ &db_length);
+ (++block_table)->n= ++n;
+ /*
+ There are not callback function for for MyISAM, and engine data
+ */
+ if (!insert_table(key_length, key, block_table,
+ db_length,
+ tables_used->table->file->table_cache_type(),
+ 0, 0))
+ DBUG_RETURN(0);
+ }
+ }
+ }
+ }
+ DBUG_RETURN(n - counter);
+}
+
/*
Store all used tables
@@ -2134,51 +2296,9 @@ my_bool Query_cache::register_all_tables(Query_cache_block *block,
Query_cache_block_table *block_table = block->table(0);
- for (n=0; tables_used; tables_used=tables_used->next, n++, block_table++)
- {
- if (tables_used->derived)
- {
- DBUG_PRINT("qcache", ("derived table skipped"));
- n--;
- block_table--;
- continue;
- }
- DBUG_PRINT("qcache",
- ("table %s, db %s, openinfo at 0x%lx, keylen %u, key at 0x%lx",
- tables_used->real_name, tables_used->db,
- (ulong) tables_used->table,
- tables_used->table->key_length,
- (ulong) tables_used->table->table_cache_key));
- block_table->n=n;
- if (!insert_table(tables_used->table->key_length,
- tables_used->table->table_cache_key, block_table,
- tables_used->db_length,
- tables_used->table->file->table_cache_type()))
- break;
-
- if (tables_used->table->db_type == DB_TYPE_MRG_MYISAM)
- {
- ha_myisammrg *handler = (ha_myisammrg *) tables_used->table->file;
- MYRG_INFO *file = handler->myrg_info();
- for (MYRG_TABLE *table = file->open_tables;
- table != file->end_table ;
- table++)
- {
- char key[MAX_DBKEY_LENGTH];
- uint32 db_length;
- uint key_length= filename_2_table_key(key, table->table->filename,
- &db_length);
- (++block_table)->n= ++n;
- if (!insert_table(key_length, key, block_table,
- db_length,
- tables_used->table->file->table_cache_type()))
- goto err;
- }
- }
- }
+ n= register_tables_from_list(tables_used, 0, block_table);
-err:
- if (tables_used)
+ if (n)
{
DBUG_PRINT("qcache", ("failed at table %d", (int) n));
/* Unlink the tables we allocated above */
@@ -2187,7 +2307,7 @@ err:
tmp++)
unlink_table(tmp);
}
- return (tables_used == 0);
+ return (n);
}
/*
@@ -2198,7 +2318,9 @@ err:
my_bool
Query_cache::insert_table(uint key_len, char *key,
Query_cache_block_table *node,
- uint32 db_length, uint8 cache_type)
+ uint32 db_length, uint8 cache_type,
+ qc_engine_callback callback,
+ ulonglong engine_data)
{
DBUG_ENTER("Query_cache::insert_table");
DBUG_PRINT("qcache", ("insert table node 0x%lx, len %d",
@@ -2208,6 +2330,23 @@ Query_cache::insert_table(uint key_len, char *key,
hash_search(&tables, (byte*) key,
key_len));
+ if (table_block &&
+ table_block->table()->engine_data() != engine_data)
+ {
+ DBUG_PRINT("qcache",
+ ("Handler require invalidation queries of %s.%s %lld-%lld",
+ table_block->table()->db(),
+ table_block->table()->table(),
+ engine_data,
+ table_block->table()->engine_data()));
+ /*
+ as far as we delete all queries with this table, table block will be
+ deleted, too
+ */
+ invalidate_table(table_block);
+ table_block= 0;
+ }
+
if (table_block == 0)
{
DBUG_PRINT("qcache", ("new table block from 0x%lx (%u)",
@@ -2238,6 +2377,8 @@ Query_cache::insert_table(uint key_len, char *key,
header->table(db + db_length + 1);
header->key_length(key_len);
header->type(cache_type);
+ header->callback(callback);
+ header->engine_data(engine_data);
}
Query_cache_block_table *list_root = table_block->table(0);
@@ -2676,6 +2817,77 @@ void Query_cache::double_linked_list_join(Query_cache_block *head_tail,
*****************************************************************************/
/*
+ Collect information about table types, check that tables are cachable and
+ count them
+
+ SYNOPSIS
+ process_and_count_tables()
+ tables_used table list for processing
+ tables_type pointer to variable for table types collection
+
+ RETURN
+ 0 error
+ >0 number of tables
+*/
+
+static TABLE_COUNTER_TYPE process_and_count_tables(TABLE_LIST *tables_used,
+ uint8 *tables_type)
+{
+ DBUG_ENTER("process_and_count_tables");
+ TABLE_COUNTER_TYPE table_count = 0;
+ for (; tables_used; tables_used= tables_used->next_global)
+ {
+ table_count++;
+ if (tables_used->view)
+ {
+ DBUG_PRINT("qcache", ("view %s, db %s",
+ tables_used->view_name.str,
+ tables_used->view_db.str));
+ *tables_type|= HA_CACHE_TBL_NONTRANSACT;
+ }
+ else
+ {
+ DBUG_PRINT("qcache", ("table %s, db %s, type %u",
+ tables_used->table->s->table_name,
+ tables_used->table->s->table_cache_key,
+ tables_used->table->s->db_type));
+ if (tables_used->derived)
+ {
+ table_count--;
+ DBUG_PRINT("qcache", ("derived table skipped"));
+ continue;
+ }
+ *tables_type|= tables_used->table->file->table_cache_type();
+
+ /*
+ table_alias_charset used here because it depends of
+ lower_case_table_names variable
+ */
+ if (tables_used->table->s->tmp_table != NO_TMP_TABLE ||
+ (*tables_type & HA_CACHE_TBL_NOCACHE) ||
+ (tables_used->db_length == 5 &&
+ my_strnncoll(table_alias_charset,
+ (uchar*)tables_used->table->s->table_cache_key, 6,
+ (uchar*)"mysql",6) == 0))
+ {
+ DBUG_PRINT("qcache",
+ ("select not cacheable: temporary, system or \
+ other non-cacheable table(s)"));
+ DBUG_RETURN(0);
+ }
+ if (tables_used->table->s->db_type == DB_TYPE_MRG_MYISAM)
+ {
+ ha_myisammrg *handler = (ha_myisammrg *)tables_used->table->file;
+ MYRG_INFO *file = handler->myrg_info();
+ table_count+= (file->end_table - file->open_tables);
+ }
+ }
+ }
+ DBUG_RETURN(table_count);
+}
+
+
+/*
If query is cacheable return number tables in query
(query without tables are not cached)
*/
@@ -2686,7 +2898,7 @@ TABLE_COUNTER_TYPE Query_cache::is_cacheable(THD *thd, uint32 query_len,
TABLE_LIST *tables_used,
uint8 *tables_type)
{
- TABLE_COUNTER_TYPE table_count = 0;
+ TABLE_COUNTER_TYPE table_count;
DBUG_ENTER("Query_cache::is_cacheable");
if (lex->sql_command == SQLCOM_SELECT &&
@@ -2700,42 +2912,8 @@ TABLE_COUNTER_TYPE Query_cache::is_cacheable(THD *thd, uint32 query_len,
lex->select_lex.options,
(int) thd->variables.query_cache_type));
- for (; tables_used; tables_used= tables_used->next)
- {
- table_count++;
- DBUG_PRINT("qcache", ("table %s, db %s, type %u",
- tables_used->real_name,
- tables_used->db, tables_used->table->db_type));
- *tables_type|= tables_used->table->file->table_cache_type();
-
- /*
- table_alias_charset used here because it depends of
- lower_case_table_names variable
- */
- if ((tables_used->table->tmp_table != NO_TMP_TABLE &&
- !tables_used->derived) ||
- (*tables_type & HA_CACHE_TBL_NOCACHE) ||
- (tables_used->db_length == 5 &&
- my_strnncoll(table_alias_charset, (uchar*)tables_used->db, 6,
- (uchar*)"mysql",6) == 0))
- {
- DBUG_PRINT("qcache",
- ("select not cacheable: temporary, system or \
-other non-cacheable table(s)"));
- DBUG_RETURN(0);
- }
- if (tables_used->derived)
- {
- table_count--;
- DBUG_PRINT("qcache", ("derived table skipped"));
- }
- else if (tables_used->table->db_type == DB_TYPE_MRG_MYISAM)
- {
- ha_myisammrg *handler = (ha_myisammrg *)tables_used->table->file;
- MYRG_INFO *file = handler->myrg_info();
- table_count+= (file->end_table - file->open_tables);
- }
- }
+ if (!(table_count= process_and_count_tables(tables_used, tables_type)))
+ DBUG_RETURN(0);
if ((thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) &&
((*tables_type)&HA_CACHE_TBL_TRANSACT))
@@ -2773,12 +2951,16 @@ my_bool Query_cache::ask_handler_allowance(THD *thd,
{
DBUG_ENTER("Query_cache::ask_handler_allowance");
- for (; tables_used; tables_used= tables_used->next)
+ for (; tables_used; tables_used= tables_used->next_global)
{
- TABLE *table= tables_used->table;
- if (!ha_caching_allowed(thd, table->table_cache_key,
- table->key_length,
- table->file->table_cache_type()))
+ TABLE *table;
+ if (!(table= tables_used->table))
+ continue;
+ handler *handler= table->file;
+ if (!handler->register_query_cache_table(thd, table->s->table_cache_key,
+ table->s->key_length,
+ &tables_used->callback_func,
+ &tables_used->engine_data))
{
DBUG_PRINT("qcache", ("Handler does not allow caching for %s.%s",
tables_used->db, tables_used->alias));
@@ -3236,7 +3418,7 @@ void Query_cache::wreck(uint line, const char *message)
DBUG_PRINT("warning", ("%5d QUERY CACHE WRECK => DISABLED",line));
DBUG_PRINT("warning", ("=================================="));
if (thd)
- thd->killed = 1;
+ thd->killed= THD::KILL_CONNECTION;
cache_dump();
/* check_integrity(0); */ /* Can't call it here because of locks */
bins_dump();