summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/r/sp.result13
-rw-r--r--mysql-test/r/view_query_cache.result25
-rw-r--r--mysql-test/t/sp.test21
-rw-r--r--mysql-test/t/view_query_cache.test31
-rw-r--r--sql/sp_head.cc1
-rw-r--r--sql/sql_cache.cc246
-rw-r--r--sql/sql_cache.h4
-rw-r--r--sql/sql_view.cc3
8 files changed, 265 insertions, 79 deletions
diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result
index 1fd519bc729..5640057bf35 100644
--- a/mysql-test/r/sp.result
+++ b/mysql-test/r/sp.result
@@ -2321,3 +2321,16 @@ select `foo` ();
`foo` ()
5
drop function `foo`;
+drop procedure if exists p1;
+create table t1(id int);
+insert into t1 values(1);
+create procedure p1()
+begin
+declare i int;
+select max(id)+1 into i from t1;
+end
+//
+call p1()//
+call p1()//
+drop procedure p1;
+drop table t1;
diff --git a/mysql-test/r/view_query_cache.result b/mysql-test/r/view_query_cache.result
index f46f0f609cd..e6c2c0152f3 100644
--- a/mysql-test/r/view_query_cache.result
+++ b/mysql-test/r/view_query_cache.result
@@ -1,3 +1,5 @@
+drop table if exists t1,t2,v1,v2,v3;
+drop view if exists t1,t2,v1,v2,v3;
set GLOBAL query_cache_size=1355776;
flush status;
create table t1 (a int, b int);
@@ -98,4 +100,27 @@ Qcache_hits 1
drop view v1;
set query_cache_type=default;
drop table t1;
+create table t1 (a int);
+insert into t1 values (1), (2), (3);
+create view v1 as select a from t1 where a > 1;
+select * from v1;
+a
+2
+3
+alter view v1 as select a from t1 where a > 2;
+select * from v1;
+a
+3
+drop view v1;
+select * from v1;
+ERROR 42S02: Table 'test.v1' doesn't exist
+drop table t1;
+create table t1 (a int, primary key (a), b int);
+create table t2 (a int, primary key (a), b int);
+insert into t2 values (1000, 2000);
+create view v3 (a,b) as select t1.a as a, t2.a as b from t1, t2;
+select * from v3;
+a b
+drop view v3;
+drop table t1, t2;
set GLOBAL query_cache_size=default;
diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test
index 4f556e34d51..4c5665aae62 100644
--- a/mysql-test/t/sp.test
+++ b/mysql-test/t/sp.test
@@ -2739,3 +2739,24 @@ drop function if exists foo;
create function `foo` () returns int return 5;
select `foo` ();
drop function `foo`;
+
+#
+# rolling back temporary Item tree changes in SP
+#
+--disable_warnings
+drop procedure if exists p1;
+--enable_warnings
+create table t1(id int);
+insert into t1 values(1);
+delimiter //;
+create procedure p1()
+begin
+ declare i int;
+ select max(id)+1 into i from t1;
+end
+//
+call p1()//
+call p1()//
+delimiter ;//
+drop procedure p1;
+drop table t1;
diff --git a/mysql-test/t/view_query_cache.test b/mysql-test/t/view_query_cache.test
index dd9c8006915..bca111a5ed1 100644
--- a/mysql-test/t/view_query_cache.test
+++ b/mysql-test/t/view_query_cache.test
@@ -2,6 +2,11 @@
#
# QUERY CACHE options for VIEWs
#
+--disable_warnings
+drop table if exists t1,t2,v1,v2,v3;
+drop view if exists t1,t2,v1,v2,v3;
+--enable_warnings
+
set GLOBAL query_cache_size=1355776;
flush status;
create table t1 (a int, b int);
@@ -53,6 +58,30 @@ drop view v1;
set query_cache_type=default;
drop table t1;
-set GLOBAL query_cache_size=default;
+#
+# invalidation of view
+#
+create table t1 (a int);
+insert into t1 values (1), (2), (3);
+create view v1 as select a from t1 where a > 1;
+select * from v1;
+alter view v1 as select a from t1 where a > 2;
+select * from v1;
+drop view v1;
+-- error 1146
+select * from v1;
+drop table t1;
+
+#
+# join view with QC
+#
+create table t1 (a int, primary key (a), b int);
+create table t2 (a int, primary key (a), b int);
+insert into t2 values (1000, 2000);
+create view v3 (a,b) as select t1.a as a, t2.a as b from t1, t2;
+select * from v3;
+drop view v3;
+drop table t1, t2;
+set GLOBAL query_cache_size=default;
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index d52474998a8..fa9e9c0d48b 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -482,6 +482,7 @@ sp_head::execute(THD *thd)
break;
DBUG_PRINT("execute", ("Instruction %u", ip));
ret= i->execute(thd, &ip);
+ thd->rollback_item_tree_changes();
if (i->free_list)
cleanup_items(i->free_list);
// Check if an exception has occurred and a handler has been found
diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc
index e38e417e6df..bda867ef3b0 100644
--- a/sql/sql_cache.cc
+++ b/sql/sql_cache.cc
@@ -311,7 +311,7 @@ TODO list:
#include "emb_qcache.h"
#endif
-#if defined(EXTRA_DEBUG) && !defined(DBUG_OFF)
+#if !defined(DBUG_OFF) && !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",\
@@ -2103,6 +2103,90 @@ void Query_cache::invalidate_table(Query_cache_block *table_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++)
+ {
+ 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);
+ {
+ TABLE_COUNTER_TYPE inc= register_tables_from_list(tables_used->ancestor,
+ n + 1,
+ block_table + 1);
+ if (!inc)
+ DBUG_RETURN(0);
+ n+= inc;
+ block_table+= inc;
+ }
+ }
+ 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
@@ -2124,52 +2208,10 @@ 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_global, n++, block_table++)
- {
- DBUG_PRINT("qcache",
- ("table %s, db %s, openinfo at 0x%lx, keylen %u, key at 0x%lx",
- tables_used->table_name, tables_used->db,
- (ulong) tables_used->table,
- tables_used->table->s->key_length,
- (ulong) tables_used->table->s->table_cache_key));
- block_table->n= n;
- 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))
- break;
-
- 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))
- 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 */
@@ -2178,7 +2220,7 @@ err:
tmp++)
unlink_table(tmp);
}
- return (tables_used == 0);
+ return (n);
}
/*
@@ -2676,6 +2718,80 @@ 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)
+ {
+
+ if (tables_used->view)
+ {
+ DBUG_PRINT("qcache", ("view %s, db %s",
+ tables_used->view_name.str,
+ tables_used->view_db.str));
+ table_count++;
+ *tables_type|= HA_CACHE_TBL_NONTRANSACT;
+ {
+ TABLE_COUNTER_TYPE subcount;
+ if (!(subcount= process_and_count_tables(tables_used->ancestor,
+ tables_type)))
+ DBUG_RETURN(0);
+ table_count+= subcount;
+ }
+ }
+ else
+ {
+ table_count++;
+ 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));
+ *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 +2802,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,36 +2816,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_global)
- {
- table_count++;
- DBUG_PRINT("qcache", ("table %s, db %s, type %u",
- tables_used->table_name,
- tables_used->db, tables_used->table->s->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->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->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->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);
- }
- }
+ 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))
@@ -2769,7 +2857,9 @@ my_bool Query_cache::ask_handler_allowance(THD *thd,
for (; tables_used; tables_used= tables_used->next_global)
{
- TABLE *table= tables_used->table;
+ 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,
diff --git a/sql/sql_cache.h b/sql/sql_cache.h
index e7116c7718a..c1b08904f51 100644
--- a/sql/sql_cache.h
+++ b/sql/sql_cache.h
@@ -285,6 +285,10 @@ protected:
void invalidate_table(TABLE *table);
void invalidate_table(byte *key, uint32 key_length);
void invalidate_table(Query_cache_block *table_block);
+ TABLE_COUNTER_TYPE
+ register_tables_from_list(TABLE_LIST *tables_used,
+ TABLE_COUNTER_TYPE counter,
+ Query_cache_block_table *block_table);
my_bool register_all_tables(Query_cache_block *block,
TABLE_LIST *tables_used,
TABLE_COUNTER_TYPE tables);
diff --git a/sql/sql_view.cc b/sql/sql_view.cc
index e2c4b1289fd..01c71599a8e 100644
--- a/sql/sql_view.cc
+++ b/sql/sql_view.cc
@@ -305,6 +305,8 @@ bool mysql_create_view(THD *thd,
VOID(pthread_mutex_lock(&LOCK_open));
res= mysql_register_view(thd, view, mode);
VOID(pthread_mutex_unlock(&LOCK_open));
+ if (view->revision != 1)
+ query_cache_invalidate3(thd, view, 0);
start_waiting_global_read_lock(thd);
if (res)
goto err;
@@ -912,6 +914,7 @@ bool mysql_drop_view(THD *thd, TABLE_LIST *views, enum_drop_mode drop_mode)
}
if (my_delete(path, MYF(MY_WME)))
goto err;
+ query_cache_invalidate3(thd, view, 0);
VOID(pthread_mutex_unlock(&LOCK_open));
}
send_ok(thd);