diff options
author | unknown <malff/marcsql@weblab.(none)> | 2007-08-20 10:45:16 -0600 |
---|---|---|
committer | unknown <malff/marcsql@weblab.(none)> | 2007-08-20 10:45:16 -0600 |
commit | 3c52b2b3a8dd0f1accc431a20d879d46fdb8c8fa (patch) | |
tree | 1c94525b5b02bd54ed10e312ac3b93eb29a4a23f | |
parent | c68c271a5fc3a88804b0243beb8dd423457c8496 (diff) | |
parent | 3ff2699500ea758adf1c021f183ec46fbe5d10b9 (diff) | |
download | mariadb-git-3c52b2b3a8dd0f1accc431a20d879d46fdb8c8fa.tar.gz |
Merge weblab.(none):/home/marcsql/TREE/mysql-5.0-base
into weblab.(none):/home/marcsql/TREE/mysql-5.0-rt-merge
sql/sql_base.cc:
Auto merged
sql/sql_handler.cc:
Auto merged
-rw-r--r-- | mysql-test/r/handler.result | 7 | ||||
-rw-r--r-- | mysql-test/r/query_cache.result | 24 | ||||
-rw-r--r-- | mysql-test/t/handler.test | 14 | ||||
-rw-r--r-- | mysql-test/t/query_cache.test | 30 | ||||
-rw-r--r-- | sql/lock.cc | 1 | ||||
-rw-r--r-- | sql/sql_base.cc | 9 | ||||
-rw-r--r-- | sql/sql_cache.cc | 24 | ||||
-rw-r--r-- | sql/sql_cache.h | 8 | ||||
-rw-r--r-- | sql/sql_handler.cc | 80 |
9 files changed, 150 insertions, 47 deletions
diff --git a/mysql-test/r/handler.result b/mysql-test/r/handler.result index 85cf47b5806..5e123df9103 100644 --- a/mysql-test/r/handler.result +++ b/mysql-test/r/handler.result @@ -482,3 +482,10 @@ ERROR 42S02: Table 'test.t1' doesn't exist drop table if exists t1; Warnings: Note 1051 Unknown table 't1' +drop table if exists t1; +create table t1 (a int) ENGINE=MEMORY; +--> client 2 +handler t1 open; +ERROR HY000: Table storage engine for 't1' doesn't have this option +--> client 1 +drop table t1; diff --git a/mysql-test/r/query_cache.result b/mysql-test/r/query_cache.result index 25c6d58dee2..25ac369481e 100644 --- a/mysql-test/r/query_cache.result +++ b/mysql-test/r/query_cache.result @@ -1621,6 +1621,30 @@ a (select count(*) from t2) 3 0 4 0 drop table t1,t2; +DROP DATABASE IF EXISTS bug30269; +CREATE DATABASE bug30269; +USE bug30269; +CREATE TABLE test1 (id int, name varchar(23)); +CREATE VIEW view1 AS SELECT id FROM test1; +INSERT INTO test1 VALUES (5, 'testit'); +GRANT SELECT (id) ON TABLE bug30269.test1 TO 'bug30269'@'localhost'; +GRANT SELECT ON TABLE bug30269.view1 TO 'bug30269'@'localhost'; +set global query_cache_size= 81920; +USE bug30269; +show status like 'Qcache_queries_in_cache'; +Variable_name Value +Qcache_queries_in_cache 0 +SELECT id FROM test1 WHERE id>2; +id +5 +SELECT id FROM view1 WHERE id>2; +id +5 +show status like 'Qcache_queries_in_cache'; +Variable_name Value +Qcache_queries_in_cache 0 +DROP DATABASE bug30269; +DROP USER 'bug30269'@'localhost'; set GLOBAL query_cache_type=default; set GLOBAL query_cache_limit=default; set GLOBAL query_cache_min_res_unit=default; diff --git a/mysql-test/t/handler.test b/mysql-test/t/handler.test index bf18b8da941..4edd5b5ec32 100644 --- a/mysql-test/t/handler.test +++ b/mysql-test/t/handler.test @@ -427,3 +427,17 @@ select * from t1; # Just to be sure and not confuse the next test case writer. drop table if exists t1; +# +# Bug#25856 - HANDLER table OPEN in one connection lock DROP TABLE in another one +# +--disable_warnings +drop table if exists t1; +--enable_warnings +create table t1 (a int) ENGINE=MEMORY; +--echo --> client 2 +connection con2; +--error 1031 +handler t1 open; +--echo --> client 1 +connection default; +drop table t1; diff --git a/mysql-test/t/query_cache.test b/mysql-test/t/query_cache.test index 3091284d061..bee089022b2 100644 --- a/mysql-test/t/query_cache.test +++ b/mysql-test/t/query_cache.test @@ -1220,9 +1220,37 @@ connection default; disconnect user1; disconnect user2; disconnect user3; + +# +# Bug #30269 Query cache eats memory +# +--disable_warnings +DROP DATABASE IF EXISTS bug30269; +--enable_warnings +CREATE DATABASE bug30269; +USE bug30269; +CREATE TABLE test1 (id int, name varchar(23)); +CREATE VIEW view1 AS SELECT id FROM test1; +INSERT INTO test1 VALUES (5, 'testit'); +GRANT SELECT (id) ON TABLE bug30269.test1 TO 'bug30269'@'localhost'; +GRANT SELECT ON TABLE bug30269.view1 TO 'bug30269'@'localhost'; +set global query_cache_size= 81920; +connect (bug30269, localhost, bug30269,,); +connection bug30269; +USE bug30269; +show status like 'Qcache_queries_in_cache'; +SELECT id FROM test1 WHERE id>2; +SELECT id FROM view1 WHERE id>2; +show status like 'Qcache_queries_in_cache'; + +connection default; +DROP DATABASE bug30269; +disconnect bug30269; +DROP USER 'bug30269'@'localhost'; + set GLOBAL query_cache_type=default; set GLOBAL query_cache_limit=default; set GLOBAL query_cache_min_res_unit=default; set GLOBAL query_cache_size=default; -# End of 5.0 tests +# End of 5.0 tests diff --git a/sql/lock.cc b/sql/lock.cc index f730ac56d35..0036d0aef77 100644 --- a/sql/lock.cc +++ b/sql/lock.cc @@ -730,6 +730,7 @@ static MYSQL_LOCK *get_lock_data(THD *thd, TABLE **table_ptr, uint count, if ((table=table_ptr[i])->s->tmp_table == NON_TRANSACTIONAL_TMP_TABLE) continue; lock_type= table->reginfo.lock_type; + DBUG_ASSERT (lock_type != TL_WRITE_DEFAULT); if (lock_type >= TL_WRITE_ALLOW_WRITE) { *write_lock_used=table; diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 1cae1c34af9..7816687c04c 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -1529,7 +1529,6 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, HASH_SEARCH_STATE state; DBUG_ENTER("open_table"); - DBUG_ASSERT (table_list->lock_type != TL_WRITE_DEFAULT); /* find a unused table in the open table cache */ if (refresh) *refresh=0; @@ -2700,11 +2699,6 @@ int open_tables(THD *thd, TABLE_LIST **start, uint *counter, uint flags) { safe_to_ignore_table= FALSE; - if (tables->lock_type == TL_WRITE_DEFAULT) - { - tables->lock_type= thd->update_lock_default; - DBUG_ASSERT (tables->lock_type >= TL_WRITE_ALLOW_WRITE); - } /* Ignore placeholders for derived tables. After derived tables processing, link to created temporary table will be put here. @@ -2849,7 +2843,8 @@ int open_tables(THD *thd, TABLE_LIST **start, uint *counter, uint flags) } if (tables->lock_type != TL_UNLOCK && ! thd->locked_tables) - tables->table->reginfo.lock_type=tables->lock_type; + tables->table->reginfo.lock_type= tables->lock_type == TL_WRITE_DEFAULT ? + thd->update_lock_default : tables->lock_type; tables->table->grant= tables->grant; process_view_routines: diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc index 33d658ce6a1..4a5bb263a5f 100644 --- a/sql/sql_cache.cc +++ b/sql/sql_cache.cc @@ -2991,14 +2991,31 @@ void Query_cache::double_linked_list_join(Query_cache_block *head_tail, >0 number of tables */ -static TABLE_COUNTER_TYPE process_and_count_tables(TABLE_LIST *tables_used, - uint8 *tables_type) +TABLE_COUNTER_TYPE +Query_cache::process_and_count_tables(THD *thd, 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++; +#ifdef HAVE_QUERY_CACHE + /* + Disable any attempt to store this statement if there are + column level grants on any referenced tables. + The grant.want_privileges flag was set to 1 in the + check_grant() function earlier if the TABLE_LIST object + had any associated column privileges. + */ + if (tables_used->grant.want_privilege) + { + DBUG_PRINT("qcache", ("Don't cache statement as it refers to " + "tables with column privileges.")); + thd->lex->safe_to_cache_query= 0; + DBUG_RETURN(0); + } +#endif if (tables_used->view) { DBUG_PRINT("qcache", ("view: %s db: %s", @@ -3071,7 +3088,8 @@ Query_cache::is_cacheable(THD *thd, uint32 query_len, char *query, LEX *lex, (long) lex->select_lex.options, (int) thd->variables.query_cache_type)); - if (!(table_count= process_and_count_tables(tables_used, tables_type))) + if (!(table_count= process_and_count_tables(thd, tables_used, + tables_type))) DBUG_RETURN(0); if ((thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) && diff --git a/sql/sql_cache.h b/sql/sql_cache.h index bc00f7ea629..34fc3a5c8d5 100644 --- a/sql/sql_cache.h +++ b/sql/sql_cache.h @@ -368,10 +368,12 @@ protected: If query is cacheable return number tables in query (query without tables not cached) */ - static TABLE_COUNTER_TYPE is_cacheable(THD *thd, uint32 query_len, char *query, - LEX *lex, TABLE_LIST *tables_used, - uint8 *tables_type); + LEX *lex, TABLE_LIST *tables_used, + uint8 *tables_type); + TABLE_COUNTER_TYPE process_and_count_tables(THD *thd, + TABLE_LIST *tables_used, + uint8 *tables_type); static my_bool ask_handler_allowance(THD *thd, TABLE_LIST *tables_used); public: diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc index 9ef955a4bc2..83c141f099f 100644 --- a/sql/sql_handler.cc +++ b/sql/sql_handler.cc @@ -119,6 +119,44 @@ static void mysql_ha_hash_free(TABLE_LIST *tables) my_free((char*) tables, MYF(0)); } +/** + Close a HANDLER table. + + @param thd Thread identifier. + @param tables A list of tables with the first entry to close. + + @note Though this function takes a list of tables, only the first list entry + will be closed. + @note Broadcasts refresh if it closed the table. +*/ + +static void mysql_ha_close_table(THD *thd, TABLE_LIST *tables) +{ + TABLE **table_ptr; + + /* + Though we could take the table pointer from hash_tables->table, + we must follow the thd->handler_tables chain anyway, as we need the + address of the 'next' pointer referencing this table + for close_thread_table(). + */ + for (table_ptr= &(thd->handler_tables); + *table_ptr && (*table_ptr != tables->table); + table_ptr= &(*table_ptr)->next) + ; + + if (*table_ptr) + { + (*table_ptr)->file->ha_index_or_rnd_end(); + VOID(pthread_mutex_lock(&LOCK_open)); + if (close_thread_table(thd, table_ptr)) + { + /* Tell threads waiting for refresh that something has happened */ + broadcast_refresh(); + } + VOID(pthread_mutex_unlock(&LOCK_open)); + } +} /* Open a HANDLER table. @@ -145,7 +183,7 @@ static void mysql_ha_hash_free(TABLE_LIST *tables) bool mysql_ha_open(THD *thd, TABLE_LIST *tables, bool reopen) { - TABLE_LIST *hash_tables; + TABLE_LIST *hash_tables = NULL; char *db, *name, *alias; uint dblen, namelen, aliaslen, counter; int error; @@ -197,7 +235,6 @@ bool mysql_ha_open(THD *thd, TABLE_LIST *tables, bool reopen) { if (! reopen) my_error(ER_ILLEGAL_HA, MYF(0), tables->alias); - mysql_ha_close(thd, tables); goto err; } @@ -225,11 +262,7 @@ bool mysql_ha_open(THD *thd, TABLE_LIST *tables, bool reopen) /* add to hash */ if (my_hash_insert(&thd->handler_tables_hash, (byte*) hash_tables)) - { - my_free((char*) hash_tables, MYF(0)); - mysql_ha_close(thd, tables); goto err; - } } if (! reopen) @@ -238,13 +271,17 @@ bool mysql_ha_open(THD *thd, TABLE_LIST *tables, bool reopen) DBUG_RETURN(FALSE); err: + if (hash_tables) + my_free((char*) hash_tables, MYF(0)); + if (tables->table) + mysql_ha_close_table(thd, tables); DBUG_PRINT("exit",("ERROR")); DBUG_RETURN(TRUE); } /* - Close a HANDLER table. + Close a HANDLER table by alias or table name SYNOPSIS mysql_ha_close() @@ -252,9 +289,8 @@ err: tables A list of tables with the first entry to close. DESCRIPTION - Though this function takes a list of tables, only the first list entry - will be closed. - Broadcasts refresh if it closed the table. + Closes the table that is associated (on the handler tables hash) with the + name (table->alias) of the specified table. RETURN FALSE ok @@ -264,7 +300,6 @@ err: bool mysql_ha_close(THD *thd, TABLE_LIST *tables) { TABLE_LIST *hash_tables; - TABLE **table_ptr; DBUG_ENTER("mysql_ha_close"); DBUG_PRINT("enter",("'%s'.'%s' as '%s'", tables->db, tables->table_name, tables->alias)); @@ -273,28 +308,7 @@ bool mysql_ha_close(THD *thd, TABLE_LIST *tables) (byte*) tables->alias, strlen(tables->alias) + 1))) { - /* - Though we could take the table pointer from hash_tables->table, - we must follow the thd->handler_tables chain anyway, as we need the - address of the 'next' pointer referencing this table - for close_thread_table(). - */ - for (table_ptr= &(thd->handler_tables); - *table_ptr && (*table_ptr != hash_tables->table); - table_ptr= &(*table_ptr)->next) - ; - - if (*table_ptr) - { - (*table_ptr)->file->ha_index_or_rnd_end(); - VOID(pthread_mutex_lock(&LOCK_open)); - if (close_thread_table(thd, table_ptr)) - { - /* Tell threads waiting for refresh that something has happened */ - broadcast_refresh(); - } - VOID(pthread_mutex_unlock(&LOCK_open)); - } + mysql_ha_close_table(thd, hash_tables); hash_delete(&thd->handler_tables_hash, (byte*) hash_tables); } else |