diff --git a/innobase/os/os0file.c b/innobase/os/os0file.c index b09c48319c3..6ed3720cc84 100644 --- a/innobase/os/os0file.c +++ b/innobase/os/os0file.c @@ -1186,7 +1186,7 @@ os_file_pread( os_file_n_pending_preads++; os_mutex_exit(os_file_count_mutex); - n_bytes = pread(file, buf, n, offs); + n_bytes = pread(file, buf, (ssize_t)n, offs); os_mutex_enter(os_file_count_mutex); os_file_n_pending_preads--; @@ -1211,7 +1211,7 @@ os_file_pread( return(ret); } - ret = read(file, buf, n); + ret = read(file, buf, (ssize_t)n); os_mutex_exit(os_file_seek_mutexes[i]); @@ -1261,7 +1261,7 @@ os_file_pwrite( os_file_n_pending_pwrites++; os_mutex_exit(os_file_count_mutex); - ret = pwrite(file, buf, n, offs); + ret = pwrite(file, buf, (ssize_t)n, offs); os_mutex_enter(os_file_count_mutex); os_file_n_pending_pwrites--; @@ -1296,7 +1296,7 @@ os_file_pwrite( return(ret); } - ret = write(file, buf, n); + ret = write(file, buf, (ssize_t)n); if (srv_unix_file_flush_method != SRV_UNIX_LITTLESYNC && srv_unix_file_flush_method != SRV_UNIX_NOSYNC diff --git a/innobase/row/row0ins.c b/innobase/row/row0ins.c index 458970da4e2..b9f860903cb 100644 --- a/innobase/row/row0ins.c +++ b/innobase/row/row0ins.c @@ -966,6 +966,23 @@ row_ins_foreign_check_on_constraint( err = row_update_cascade_for_mysql(thr, cascade, foreign->foreign_table); + + if (foreign->foreign_table->n_foreign_key_checks_running == 0) { + fprintf(stderr, +"InnoDB: error: table %s has the counter 0 though there is\n" +"InnoDB: a FOREIGN KEY check running on it.\n", + foreign->foreign_table->name); + } + + /* Release the data dictionary latch for a while, so that we do not + starve other threads from doing CREATE TABLE etc. if we have a huge + cascaded operation running. The counter n_foreign_key_checks_running + will prevent other users from dropping or ALTERing the table when we + release the latch. */ + + row_mysql_unfreeze_data_dictionary(thr_get_trx(thr)); + row_mysql_freeze_data_dictionary(thr_get_trx(thr)); + mtr_start(mtr); /* Restore pcur position */ diff --git a/innobase/row/row0mysql.c b/innobase/row/row0mysql.c index a884dc8d9ef..3eb4f0de60e 100644 --- a/innobase/row/row0mysql.c +++ b/innobase/row/row0mysql.c @@ -2156,8 +2156,8 @@ row_drop_table_for_mysql( fputs(" InnoDB: You are trying to drop table ", stderr); ut_print_name(stderr, table->name); fputs("\n" - "InnoDB: though there are foreign key check running on it.\n" - "InnoDB: Adding the table to the background drop queue.\n", + "InnoDB: though there is a foreign key check running on it.\n" + "InnoDB: Adding the table to the background drop queue.\n", stderr); row_add_table_to_background_drop_list(table); diff --git a/mysql-test/r/query_cache.result b/mysql-test/r/query_cache.result index a9e9f167e5f..85fe77b1f10 100644 --- a/mysql-test/r/query_cache.result +++ b/mysql-test/r/query_cache.result @@ -704,4 +704,17 @@ Qcache_queries_in_cache 1 unlock table; drop table t1,t2; set query_cache_wlock_invalidate=default; +CREATE TABLE t1 (id INT PRIMARY KEY); +insert into t1 values (1),(2),(3); +select * from t1; +id +1 +2 +3 +create temporary table t1 (a int not null auto_increment +primary key); +select * from t1; +a +drop table t1; +drop table t1; set GLOBAL query_cache_size=0; diff --git a/mysql-test/t/query_cache.test b/mysql-test/t/query_cache.test index 8a07c0a53a0..61fbadde1e1 100644 --- a/mysql-test/t/query_cache.test +++ b/mysql-test/t/query_cache.test @@ -521,4 +521,16 @@ unlock table; drop table t1,t2; set query_cache_wlock_invalidate=default; +# +# hiding real table stored in query cache by temporary table +# +CREATE TABLE t1 (id INT PRIMARY KEY); +insert into t1 values (1),(2),(3); +select * from t1; +create temporary table t1 (a int not null auto_increment +primary key); +select * from t1; +drop table t1; +drop table t1; + set GLOBAL query_cache_size=0; diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index b5e571e74d0..b123927d09e 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -551,6 +551,7 @@ int mysql_ha_flush(THD *thd, TABLE_LIST *tables, uint mode_flags); #define MYSQL_HA_FLUSH_ALL 0x02 /* sql_base.cc */ +#define TMP_TABLE_KEY_EXTRA 8 void set_item_name(Item *item,char *pos,uint length); bool add_field_to_list(char *field_name, enum enum_field_types type, char *length, char *decimal, diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 72400bf0abb..ddc81053357 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -816,8 +816,9 @@ TABLE *open_table(THD *thd,const char *db,const char *table_name, for (table=thd->temporary_tables; table ; table=table->next) { - if (table->key_length == key_length+8 && - !memcmp(table->table_cache_key,key,key_length+8)) + if (table->key_length == key_length + TMP_TABLE_KEY_EXTRA && + !memcmp(table->table_cache_key, key, + key_length + TMP_TABLE_KEY_EXTRA)) { if (table->query_id == thd->query_id) { diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc index 60f0cfadc8e..f503a63e752 100644 --- a/sql/sql_cache.cc +++ b/sql/sql_cache.cc @@ -971,9 +971,38 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length) for (; block_table != block_table_end; block_table++) { TABLE_LIST table_list; - bzero((char*) &table_list,sizeof(table_list)); + TABLE *tmptable; Query_cache_table *table = block_table->parent; + + /* + Check that we have not temporary tables with same names of tables + of this query. If we have such tables, we will not send data from + query cache, because temporary tables hide real tables by which + query in query cache was made. + */ + for (tmptable= thd->temporary_tables; tmptable ; tmptable= tmptable->next) + { + if (tmptable->key_length - TMP_TABLE_KEY_EXTRA == table->key_len() && + !memcmp(tmptable->table_cache_key, table->data(), + table->key_len())) + { + DBUG_PRINT("qcache", + ("Temporary table detected: '%s.%s'", + table_list.db, table_list.alias)); + STRUCT_UNLOCK(&structure_guard_mutex); + /* + We should not store result of this query because it contain + temporary tables => assign following variable to make check + faster. + */ + thd->safe_to_cache_query=0; + BLOCK_UNLOCK_RD(query_block); + DBUG_RETURN(-1); + } + } + + bzero((char*) &table_list,sizeof(table_list)); table_list.db = table->db(); table_list.alias= table_list.real_name= table->table(); if (check_table_access(thd,SELECT_ACL,&table_list,1)) @@ -2066,6 +2095,7 @@ Query_cache::insert_table(uint key_len, char *key, } char *db = header->db(); header->table(db + db_length + 1); + header->key_len(key_len); } Query_cache_block_table *list_root = table_block->table(0); diff --git a/sql/sql_cache.h b/sql/sql_cache.h index 0c6579250ab..454f0318c12 100644 --- a/sql/sql_cache.h +++ b/sql/sql_cache.h @@ -144,10 +144,13 @@ struct Query_cache_query struct Query_cache_table { char *tbl; + uint32 key_length; inline char *db() { return (char *) data(); } inline char *table() { return tbl; } inline void table(char *table) { tbl = table; } + inline uint32 key_len() { return key_length; } + inline void key_len(uint32 len) { key_length= len; } inline gptr data() { return (gptr)(((byte*)this)+ diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 1fe9e5093eb..6b3723d89c4 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1142,7 +1142,9 @@ bool dispatch_command(enum enum_server_command command, THD *thd, if (check_access(thd,CREATE_ACL,db,0,1)) break; mysql_log.write(thd,command,packet); - mysql_create_db(thd,(lower_case_table_names == 2 ? alias : db),0,0); + if (mysql_create_db(thd, (lower_case_table_names == 2 ? alias : db), + 0, 0) < 0) + send_error(&thd->net, thd->killed ? ER_SERVER_SHUTDOWN : 0); break; } case COM_DROP_DB: // QQ: To be removed @@ -1163,7 +1165,9 @@ bool dispatch_command(enum enum_server_command command, THD *thd, break; } mysql_log.write(thd,command,db); - mysql_rm_db(thd, (lower_case_table_names == 2 ? alias : db), 0, 0); + if (mysql_rm_db(thd, (lower_case_table_names == 2 ? alias : db), + 0, 0) < 0) + send_error(&thd->net, thd->killed ? ER_SERVER_SHUTDOWN : 0); break; } case COM_BINLOG_DUMP: