Loading mysql-test/r/sp.result +12 −0 Original line number Diff line number Diff line Loading @@ -2480,5 +2480,17 @@ ERROR 42000: Can't find any matching row in the user table select bug5278()| ERROR 42000: Can't find any matching row in the user table drop function bug5278| drop procedure if exists p1| create table t3(id int)| insert into t3 values(1)| create procedure bug7992() begin declare i int; select max(id)+1 into i from t3; end| call bug7992()| call bug7992()| drop procedure bug7992| drop table t3| drop table t1; drop table t2; mysql-test/r/view_query_cache.result +25 −0 Original line number Diff line number Diff line 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); Loading Loading @@ -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; mysql-test/t/sp.test +19 −0 Original line number Diff line number Diff line Loading @@ -2982,7 +2982,26 @@ select bug5278()| select bug5278()| drop function bug5278| # # BUG#7992: rolling back temporary Item tree changes in SP # --disable_warnings drop procedure if exists p1| --enable_warnings create table t3(id int)| insert into t3 values(1)| create procedure bug7992() begin declare i int; select max(id)+1 into i from t3; end| call bug7992()| call bug7992()| drop procedure bug7992| drop table t3| delimiter ;| drop table t1; drop table t2; mysql-test/t/view_query_cache.test +30 −1 Original line number Diff line number Diff line Loading @@ -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); Loading Loading @@ -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; sql/sql_cache.cc +181 −78 Original line number Diff line number Diff line Loading @@ -311,7 +311,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",\ Loading Loading @@ -2103,45 +2103,76 @@ void Query_cache::invalidate_table(Query_cache_block *table_block) } } /* Store all used tables Register given table list begining with given position in tables table of block SYNOPSIS register_all_tables() block Store tables in this block tables_used List if used tables tables_arg Not used ? 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 */ my_bool Query_cache::register_all_tables(Query_cache_block *block, TABLE_LIST *tables_used, TABLE_COUNTER_TYPE tables_arg) 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_PRINT("qcache", ("register tables block 0x%lx, n %d, header %x", (ulong) block, (int) tables_arg, (int) ALIGN_SIZE(sizeof(Query_cache_block)))); Query_cache_block_table *block_table = block->table(0); for (n= 0; 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_name, tables_used->db, 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)); 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; DBUG_RETURN(0); if (tables_used->table->s->db_type == DB_TYPE_MRG_MYISAM) { Loading @@ -2163,13 +2194,39 @@ my_bool Query_cache::register_all_tables(Query_cache_block *block, db_length, tables_used->table->file->table_cache_type(), 0, 0)) goto err; DBUG_RETURN(0); } } } } DBUG_RETURN(n - counter); } /* Store all used tables SYNOPSIS register_all_tables() block Store tables in this block tables_used List if used tables tables_arg Not used ? */ my_bool Query_cache::register_all_tables(Query_cache_block *block, TABLE_LIST *tables_used, TABLE_COUNTER_TYPE tables_arg) { TABLE_COUNTER_TYPE n; DBUG_PRINT("qcache", ("register tables block 0x%lx, n %d, header %x", (ulong) block, (int) tables_arg, (int) ALIGN_SIZE(sizeof(Query_cache_block)))); Query_cache_block_table *block_table = block->table(0); 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 */ Loading @@ -2178,7 +2235,7 @@ my_bool Query_cache::register_all_tables(Query_cache_block *block, tmp++) unlink_table(tmp); } return (tables_used == 0); return (n); } /* Loading Loading @@ -2676,36 +2733,47 @@ void Query_cache::double_linked_list_join(Query_cache_block *head_tail, *****************************************************************************/ /* If query is cacheable return number tables in query (query without tables are not cached) 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 */ TABLE_COUNTER_TYPE Query_cache::is_cacheable(THD *thd, uint32 query_len, char *query, LEX *lex, TABLE_LIST *tables_used, 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; DBUG_ENTER("Query_cache::is_cacheable"); if (lex->sql_command == SQLCOM_SELECT && (thd->variables.query_cache_type == 1 || (thd->variables.query_cache_type == 2 && (lex->select_lex.options & OPTION_TO_QUERY_CACHE))) && lex->safe_to_cache_query) { DBUG_PRINT("qcache", ("options %lx %lx, type %u", OPTION_TO_QUERY_CACHE, lex->select_lex.options, (int) thd->variables.query_cache_type)); 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; { TABLE_COUNTER_TYPE subcount; if (!(subcount= process_and_count_tables(tables_used->ancestor, tables_type))) DBUG_RETURN(0); table_count+= subcount; } } else { DBUG_PRINT("qcache", ("table %s, db %s, type %u", tables_used->table_name, tables_used->db, tables_used->table->s->db_type)); 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(); /* Loading @@ -2715,7 +2783,8 @@ TABLE_COUNTER_TYPE Query_cache::is_cacheable(THD *thd, uint32 query_len, 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, my_strnncoll(table_alias_charset, (uchar*)tables_used->table->s->table_cache_key, 6, (uchar*)"mysql",6) == 0)) { DBUG_PRINT("qcache", Loading @@ -2730,6 +2799,38 @@ other non-cacheable table(s)")); 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) */ TABLE_COUNTER_TYPE Query_cache::is_cacheable(THD *thd, uint32 query_len, char *query, LEX *lex, TABLE_LIST *tables_used, uint8 *tables_type) { TABLE_COUNTER_TYPE table_count; DBUG_ENTER("Query_cache::is_cacheable"); if (lex->sql_command == SQLCOM_SELECT && (thd->variables.query_cache_type == 1 || (thd->variables.query_cache_type == 2 && (lex->select_lex.options & OPTION_TO_QUERY_CACHE))) && lex->safe_to_cache_query) { DBUG_PRINT("qcache", ("options %lx %lx, type %u", OPTION_TO_QUERY_CACHE, lex->select_lex.options, (int) thd->variables.query_cache_type)); 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)) Loading Loading @@ -2769,7 +2870,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, Loading Loading
mysql-test/r/sp.result +12 −0 Original line number Diff line number Diff line Loading @@ -2480,5 +2480,17 @@ ERROR 42000: Can't find any matching row in the user table select bug5278()| ERROR 42000: Can't find any matching row in the user table drop function bug5278| drop procedure if exists p1| create table t3(id int)| insert into t3 values(1)| create procedure bug7992() begin declare i int; select max(id)+1 into i from t3; end| call bug7992()| call bug7992()| drop procedure bug7992| drop table t3| drop table t1; drop table t2;
mysql-test/r/view_query_cache.result +25 −0 Original line number Diff line number Diff line 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); Loading Loading @@ -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;
mysql-test/t/sp.test +19 −0 Original line number Diff line number Diff line Loading @@ -2982,7 +2982,26 @@ select bug5278()| select bug5278()| drop function bug5278| # # BUG#7992: rolling back temporary Item tree changes in SP # --disable_warnings drop procedure if exists p1| --enable_warnings create table t3(id int)| insert into t3 values(1)| create procedure bug7992() begin declare i int; select max(id)+1 into i from t3; end| call bug7992()| call bug7992()| drop procedure bug7992| drop table t3| delimiter ;| drop table t1; drop table t2;
mysql-test/t/view_query_cache.test +30 −1 Original line number Diff line number Diff line Loading @@ -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); Loading Loading @@ -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;
sql/sql_cache.cc +181 −78 Original line number Diff line number Diff line Loading @@ -311,7 +311,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",\ Loading Loading @@ -2103,45 +2103,76 @@ void Query_cache::invalidate_table(Query_cache_block *table_block) } } /* Store all used tables Register given table list begining with given position in tables table of block SYNOPSIS register_all_tables() block Store tables in this block tables_used List if used tables tables_arg Not used ? 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 */ my_bool Query_cache::register_all_tables(Query_cache_block *block, TABLE_LIST *tables_used, TABLE_COUNTER_TYPE tables_arg) 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_PRINT("qcache", ("register tables block 0x%lx, n %d, header %x", (ulong) block, (int) tables_arg, (int) ALIGN_SIZE(sizeof(Query_cache_block)))); Query_cache_block_table *block_table = block->table(0); for (n= 0; 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_name, tables_used->db, 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)); 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; DBUG_RETURN(0); if (tables_used->table->s->db_type == DB_TYPE_MRG_MYISAM) { Loading @@ -2163,13 +2194,39 @@ my_bool Query_cache::register_all_tables(Query_cache_block *block, db_length, tables_used->table->file->table_cache_type(), 0, 0)) goto err; DBUG_RETURN(0); } } } } DBUG_RETURN(n - counter); } /* Store all used tables SYNOPSIS register_all_tables() block Store tables in this block tables_used List if used tables tables_arg Not used ? */ my_bool Query_cache::register_all_tables(Query_cache_block *block, TABLE_LIST *tables_used, TABLE_COUNTER_TYPE tables_arg) { TABLE_COUNTER_TYPE n; DBUG_PRINT("qcache", ("register tables block 0x%lx, n %d, header %x", (ulong) block, (int) tables_arg, (int) ALIGN_SIZE(sizeof(Query_cache_block)))); Query_cache_block_table *block_table = block->table(0); 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 */ Loading @@ -2178,7 +2235,7 @@ my_bool Query_cache::register_all_tables(Query_cache_block *block, tmp++) unlink_table(tmp); } return (tables_used == 0); return (n); } /* Loading Loading @@ -2676,36 +2733,47 @@ void Query_cache::double_linked_list_join(Query_cache_block *head_tail, *****************************************************************************/ /* If query is cacheable return number tables in query (query without tables are not cached) 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 */ TABLE_COUNTER_TYPE Query_cache::is_cacheable(THD *thd, uint32 query_len, char *query, LEX *lex, TABLE_LIST *tables_used, 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; DBUG_ENTER("Query_cache::is_cacheable"); if (lex->sql_command == SQLCOM_SELECT && (thd->variables.query_cache_type == 1 || (thd->variables.query_cache_type == 2 && (lex->select_lex.options & OPTION_TO_QUERY_CACHE))) && lex->safe_to_cache_query) { DBUG_PRINT("qcache", ("options %lx %lx, type %u", OPTION_TO_QUERY_CACHE, lex->select_lex.options, (int) thd->variables.query_cache_type)); 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; { TABLE_COUNTER_TYPE subcount; if (!(subcount= process_and_count_tables(tables_used->ancestor, tables_type))) DBUG_RETURN(0); table_count+= subcount; } } else { DBUG_PRINT("qcache", ("table %s, db %s, type %u", tables_used->table_name, tables_used->db, tables_used->table->s->db_type)); 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(); /* Loading @@ -2715,7 +2783,8 @@ TABLE_COUNTER_TYPE Query_cache::is_cacheable(THD *thd, uint32 query_len, 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, my_strnncoll(table_alias_charset, (uchar*)tables_used->table->s->table_cache_key, 6, (uchar*)"mysql",6) == 0)) { DBUG_PRINT("qcache", Loading @@ -2730,6 +2799,38 @@ other non-cacheable table(s)")); 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) */ TABLE_COUNTER_TYPE Query_cache::is_cacheable(THD *thd, uint32 query_len, char *query, LEX *lex, TABLE_LIST *tables_used, uint8 *tables_type) { TABLE_COUNTER_TYPE table_count; DBUG_ENTER("Query_cache::is_cacheable"); if (lex->sql_command == SQLCOM_SELECT && (thd->variables.query_cache_type == 1 || (thd->variables.query_cache_type == 2 && (lex->select_lex.options & OPTION_TO_QUERY_CACHE))) && lex->safe_to_cache_query) { DBUG_PRINT("qcache", ("options %lx %lx, type %u", OPTION_TO_QUERY_CACHE, lex->select_lex.options, (int) thd->variables.query_cache_type)); 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)) Loading Loading @@ -2769,7 +2870,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, Loading