summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorIgor Babaev <igor@askmonty.org>2012-07-30 23:08:05 -0700
committerIgor Babaev <igor@askmonty.org>2012-07-30 23:08:05 -0700
commit3116e3ad6164c96edc2a27c3438f325c4dc464f3 (patch)
treea46cf41ad73a7f87c4679ea9d26d90af27b84753 /sql
parente13cd5abc1fc194eca36ed3ea145a114a3001627 (diff)
parent257fd9d3d9b5755128e0a226c26e5b5a0464b9ca (diff)
downloadmariadb-git-3116e3ad6164c96edc2a27c3438f325c4dc464f3.tar.gz
Merge 5.5 -> 5.5-mwl248.
Diffstat (limited to 'sql')
-rw-r--r--sql/ha_partition.cc127
-rw-r--r--sql/ha_partition.h26
-rw-r--r--sql/handler.cc4
-rw-r--r--sql/handler.h42
-rw-r--r--sql/item_subselect.cc2
-rw-r--r--sql/mysql_install_db.cc2
-rw-r--r--sql/opt_range.cc17
-rw-r--r--sql/sql_cache.cc94
-rw-r--r--sql/sql_cache.h31
-rw-r--r--sql/table.cc9
10 files changed, 260 insertions, 94 deletions
diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc
index b4181fc6d7f..78adbeff623 100644
--- a/sql/ha_partition.cc
+++ b/sql/ha_partition.cc
@@ -2076,6 +2076,133 @@ partition_element *ha_partition::find_partition_element(uint part_id)
return NULL;
}
+uint ha_partition::count_query_cache_dependant_tables(uint8 *tables_type)
+{
+ DBUG_ENTER("ha_partition::count_query_cache_dependant_tables");
+ /* Here we rely on the fact that all tables are of the same type */
+ uint8 type= m_file[0]->table_cache_type();
+ (*tables_type)|= type;
+ DBUG_PRINT("info", ("cnt: %u", (uint)m_tot_parts));
+ /*
+ We need save underlying tables only for HA_CACHE_TBL_ASKTRANSACT:
+ HA_CACHE_TBL_NONTRANSACT - because all changes goes through partition table
+ HA_CACHE_TBL_NOCACHE - because will not be cached
+ HA_CACHE_TBL_TRANSACT - QC need to know that such type present
+ */
+ DBUG_RETURN(type == HA_CACHE_TBL_ASKTRANSACT ? m_tot_parts : 0);
+}
+
+my_bool ha_partition::reg_query_cache_dependant_table(THD *thd,
+ char *key, uint key_len,
+ uint8 type,
+ Query_cache *cache,
+ Query_cache_block_table **block_table,
+ handler *file,
+ uint *n)
+{
+ DBUG_ENTER("ha_partition::reg_query_cache_dependant_table");
+ qc_engine_callback engine_callback;
+ ulonglong engine_data;
+ /* ask undelying engine */
+ if (!file->register_query_cache_table(thd, key,
+ key_len,
+ &engine_callback,
+ &engine_data))
+ {
+ DBUG_PRINT("qcache", ("Handler does not allow caching for %s.%s",
+ key,
+ key + table_share->db.length + 1));
+ /*
+ As this can change from call to call, don't reset set
+ thd->lex->safe_to_cache_query
+ */
+ thd->query_cache_is_applicable= 0; // Query can't be cached
+ DBUG_RETURN(TRUE);
+ }
+ (++(*block_table))->n= ++(*n);
+ if (!cache->insert_table(key_len,
+ key, (*block_table),
+ table_share->db.length,
+ type,
+ engine_callback, engine_data,
+ FALSE))
+ DBUG_RETURN(TRUE);
+ DBUG_RETURN(FALSE);
+}
+
+
+my_bool ha_partition::register_query_cache_dependant_tables(THD *thd,
+ Query_cache *cache,
+ Query_cache_block_table **block_table,
+ uint *n)
+{
+ char *name;
+ uint prefix_length= table_share->table_cache_key.length + 3;
+ uint num_parts= m_part_info->num_parts;
+ uint num_subparts= m_part_info->num_subparts;
+ uint i= 0;
+ List_iterator<partition_element> part_it(m_part_info->partitions);
+ char key[FN_REFLEN];
+
+ DBUG_ENTER("ha_partition::register_query_cache_dependant_tables");
+
+ /* see ha_partition::count_query_cache_dependant_tables */
+ if (m_file[0]->table_cache_type() != HA_CACHE_TBL_ASKTRANSACT)
+ DBUG_RETURN(FALSE); // nothing to register
+
+ /* prepare static part of the key */
+ memmove(key, table_share->table_cache_key.str,
+ table_share->table_cache_key.length);
+
+ name= key + table_share->table_cache_key.length - 1;
+ name[0]= name[2]= '#';
+ name[1]= 'P';
+ name+= 3;
+
+ do
+ {
+ partition_element *part_elem= part_it++;
+ uint part_len= strmov(name, part_elem->partition_name) - name;
+ if (m_is_sub_partitioned)
+ {
+ List_iterator<partition_element> subpart_it(part_elem->subpartitions);
+ partition_element *sub_elem;
+ char *sname= name + part_len;
+ uint j= 0, part;
+ sname[0]= sname[3]= '#';
+ sname[1]= 'S';
+ sname[2]= 'P';
+ sname += 4;
+ do
+ {
+ sub_elem= subpart_it++;
+ part= i * num_subparts + j;
+ uint spart_len= strmov(sname, sub_elem->partition_name) - name + 1;
+ if (reg_query_cache_dependant_table(thd, key,
+ prefix_length + part_len + 4 +
+ spart_len,
+ m_file[part]->table_cache_type(),
+ cache,
+ block_table, m_file[part],
+ n))
+ DBUG_RETURN(TRUE);
+ } while (++j < num_subparts);
+ }
+ else
+ {
+ if (reg_query_cache_dependant_table(thd, key,
+ prefix_length + part_len + 1,
+ m_file[i]->table_cache_type(),
+ cache,
+ block_table, m_file[i],
+ n))
+ DBUG_RETURN(TRUE);
+ }
+ } while (++i < num_parts);
+ DBUG_PRINT("info", ("cnt: %u", (uint)m_tot_parts));
+ DBUG_RETURN(FALSE);
+}
+
/*
Set up table share object before calling create on underlying handler
diff --git a/sql/ha_partition.h b/sql/ha_partition.h
index aa9179f9f69..0f922394ec5 100644
--- a/sql/ha_partition.h
+++ b/sql/ha_partition.h
@@ -544,22 +544,20 @@ public:
virtual int extra(enum ha_extra_function operation);
virtual int extra_opt(enum ha_extra_function operation, ulong cachesize);
virtual int reset(void);
- /*
- Do not allow caching of partitioned tables, since we cannot return
- a callback or engine_data that would work for a generic engine.
- */
- virtual my_bool register_query_cache_table(THD *thd, char *table_key,
- uint key_length,
- qc_engine_callback
- *engine_callback,
- ulonglong *engine_data)
- {
- *engine_callback= NULL;
- *engine_data= 0;
- return FALSE;
- }
+ virtual uint count_query_cache_dependant_tables(uint8 *tables_type);
+ virtual my_bool
+ register_query_cache_dependant_tables(THD *thd,
+ Query_cache *cache,
+ Query_cache_block_table **block,
+ uint *n);
private:
+ my_bool reg_query_cache_dependant_table(THD *thd,
+ char *key, uint key_len, uint8 type,
+ Query_cache *cache,
+ Query_cache_block_table
+ **block_table,
+ handler *file, uint *n);
static const uint NO_CURRENT_PART_ID;
int loop_extra(enum ha_extra_function operation);
void late_extra_cache(uint partition_id);
diff --git a/sql/handler.cc b/sql/handler.cc
index b7d545a75dc..ecd02e2a1be 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -504,10 +504,6 @@ int ha_initialize_handlerton(st_plugin_int *plugin)
"Assigning value %d.", plugin->plugin->name, idx);
hton->db_type= (enum legacy_db_type) idx;
}
- installed_htons[hton->db_type]= hton;
- tmp= hton->savepoint_offset;
- hton->savepoint_offset= savepoint_alloc_size;
- savepoint_alloc_size+= tmp;
/*
In case a plugin is uninstalled and re-installed later, it should
diff --git a/sql/handler.h b/sql/handler.h
index ee1731af563..9c0850e157a 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -1689,6 +1689,8 @@ public:
virtual ~handler_add_index() {}
};
+class Query_cache;
+struct Query_cache_block_table;
/**
The handler class is the interface for dynamically loadable
storage engines. Do not add ifdefs and take care when adding or
@@ -2522,6 +2524,46 @@ public:
return TRUE;
}
+ /*
+ Count tables invisible from all tables list on which current one built
+ (like myisammrg and partitioned tables)
+
+ tables_type mask for the tables should be added herdde
+
+ returns number of such tables
+ */
+
+ virtual uint count_query_cache_dependant_tables(uint8 *tables_type
+ __attribute__((unused)))
+ {
+ return 0;
+ }
+
+ /*
+ register tables invisible from all tables list on which current one built
+ (like myisammrg and partitioned tables).
+
+ @note they should be counted by method above
+
+ cache Query cache pointer
+ block Query cache block to write the table
+ n Number of the table
+
+ @retval FALSE - OK
+ @retval TRUE - Error
+ */
+
+ virtual my_bool
+ register_query_cache_dependant_tables(THD *thd
+ __attribute__((unused)),
+ Query_cache *cache
+ __attribute__((unused)),
+ Query_cache_block_table **block
+ __attribute__((unused)),
+ uint *n __attribute__((unused)))
+ {
+ return FALSE;
+ }
/*
Check if the primary key (if there is one) is a clustered and a
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index 4a8e1393a22..49d232d31be 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -287,7 +287,7 @@ bool Item_subselect::fix_fields(THD *thd_param, Item **ref)
else
goto end;
- if ((uncacheable= engine->uncacheable()))
+ if ((uncacheable= engine->uncacheable() & ~UNCACHEABLE_EXPLAIN))
{
const_item_cache= 0;
if (uncacheable & UNCACHEABLE_RAND)
diff --git a/sql/mysql_install_db.cc b/sql/mysql_install_db.cc
index bde81d915b2..6e2c6ec07f3 100644
--- a/sql/mysql_install_db.cc
+++ b/sql/mysql_install_db.cc
@@ -247,7 +247,7 @@ static char *init_bootstrap_command_line(char *cmdline, size_t size)
"\"\"%s\" --no-defaults --bootstrap"
" \"--language=%s\\share\\english\""
" --basedir=. --datadir=. --default-storage-engine=myisam"
- " --max_allowed_packet=9M --loose-skip-innodb --loose-skip-pbxt"
+ " --max_allowed_packet=9M --loose-skip-innodb"
" --net-buffer-length=16k\"", mysqld_path, basedir);
return cmdline;
}
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index 7a8beb76c0c..e373e5197fe 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -2008,7 +2008,7 @@ int QUICK_RANGE_SELECT::init_ror_merged_scan(bool reuse_handler)
if (reuse_handler)
{
DBUG_PRINT("info", ("Reusing handler 0x%lx", (long) file));
- if (init() || reset())
+ if (init())
{
DBUG_RETURN(1);
}
@@ -2043,7 +2043,7 @@ int QUICK_RANGE_SELECT::init_ror_merged_scan(bool reuse_handler)
if (file->ha_external_lock(thd, F_RDLCK))
goto failure;
- if (init() || reset())
+ if (init())
{
file->ha_external_lock(thd, F_UNLCK);
file->ha_close();
@@ -2090,7 +2090,18 @@ end:
head->key_read= org_key_read;
bitmap_copy(&column_bitmap, head->read_set);
head->column_bitmaps_set(&column_bitmap, &column_bitmap);
-
+
+ if (reset())
+ {
+ if (!reuse_handler)
+ {
+ file->ha_external_lock(thd, F_UNLCK);
+ file->ha_close();
+ goto failure;
+ }
+ else
+ DBUG_RETURN(1);
+ }
DBUG_RETURN(0);
failure:
diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc
index 96814562757..7edd28446a2 100644
--- a/sql/sql_cache.cc
+++ b/sql/sql_cache.cc
@@ -1533,7 +1533,7 @@ def_week_frmt: %lu, in_trans: %d, autocommit: %d",
unlock();
goto end;
}
- if (!register_all_tables(query_block, tables_used, local_tables))
+ if (!register_all_tables(thd, query_block, tables_used, local_tables))
{
refused++;
DBUG_PRINT("warning", ("tables list including failed"));
@@ -3203,6 +3203,7 @@ Query_cache::invalidate_query_block_list(THD *thd,
SYNOPSIS
Query_cache::register_tables_from_list
+ thd thread handle
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
@@ -3213,24 +3214,24 @@ Query_cache::invalidate_query_block_list(THD *thd,
*/
TABLE_COUNTER_TYPE
-Query_cache::register_tables_from_list(TABLE_LIST *tables_used,
+Query_cache::register_tables_from_list(THD *thd, TABLE_LIST *tables_used,
TABLE_COUNTER_TYPE counter,
- Query_cache_block_table *block_table)
+ 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++)
+ tables_used= tables_used->next_global, n++, (*block_table)++)
{
if (tables_used->is_anonymous_derived_table())
{
DBUG_PRINT("qcache", ("derived table skipped"));
n--;
- block_table--;
+ (*block_table)--;
continue;
}
- block_table->n= n;
+ (*block_table)->n= n;
if (tables_used->view)
{
char key[MAX_DBKEY_LENGTH];
@@ -3243,9 +3244,9 @@ Query_cache::register_tables_from_list(TABLE_LIST *tables_used,
/*
There are not callback function for for VIEWs
*/
- if (!insert_table(key_length, key, block_table,
+ if (!insert_table(key_length, key, (*block_table),
tables_used->view_db.length + 1,
- HA_CACHE_TBL_NONTRANSACT, 0, 0))
+ HA_CACHE_TBL_NONTRANSACT, 0, 0, TRUE))
DBUG_RETURN(0);
/*
We do not need to register view tables here because they are already
@@ -3264,42 +3265,17 @@ Query_cache::register_tables_from_list(TABLE_LIST *tables_used,
if (!insert_table(tables_used->table->s->table_cache_key.length,
tables_used->table->s->table_cache_key.str,
- block_table,
+ (*block_table),
tables_used->db_length,
tables_used->table->file->table_cache_type(),
tables_used->callback_func,
- tables_used->engine_data))
+ tables_used->engine_data,
+ TRUE))
DBUG_RETURN(0);
-#ifdef WITH_MYISAMMRG_STORAGE_ENGINE
- /*
- XXX FIXME: Some generic mechanism is required here instead of this
- MYISAMMRG-specific implementation.
- */
- if (tables_used->table->s->db_type()->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);
- }
- }
-#endif
+ if (tables_used->table->file->
+ register_query_cache_dependant_tables(thd, this, block_table, &n))
+ DBUG_RETURN(0);
}
}
DBUG_RETURN(n - counter);
@@ -3310,12 +3286,14 @@ Query_cache::register_tables_from_list(TABLE_LIST *tables_used,
SYNOPSIS
register_all_tables()
+ thd Thread handle
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,
+my_bool Query_cache::register_all_tables(THD *thd,
+ Query_cache_block *block,
TABLE_LIST *tables_used,
TABLE_COUNTER_TYPE tables_arg)
{
@@ -3326,7 +3304,7 @@ my_bool Query_cache::register_all_tables(Query_cache_block *block,
Query_cache_block_table *block_table = block->table(0);
- n= register_tables_from_list(tables_used, 0, block_table);
+ n= register_tables_from_list(thd, tables_used, 0, &block_table);
if (n==0)
{
@@ -3335,6 +3313,8 @@ my_bool Query_cache::register_all_tables(Query_cache_block *block,
tmp != block_table;
tmp++)
unlink_table(tmp);
+ if (block_table->parent)
+ unlink_table(block_table);
}
return test(n);
}
@@ -3353,7 +3333,8 @@ Query_cache::insert_table(uint key_len, char *key,
Query_cache_block_table *node,
uint32 db_length, uint8 cache_type,
qc_engine_callback callback,
- ulonglong engine_data)
+ ulonglong engine_data,
+ my_bool hash)
{
DBUG_ENTER("Query_cache::insert_table");
DBUG_PRINT("qcache", ("insert table node 0x%lx, len %d",
@@ -3361,8 +3342,10 @@ Query_cache::insert_table(uint key_len, char *key,
THD *thd= current_thd;
- Query_cache_block *table_block=
- (Query_cache_block *) my_hash_search(&tables, (uchar*) key, key_len);
+ Query_cache_block *table_block=
+ (hash ?
+ (Query_cache_block *) my_hash_search(&tables, (uchar*) key, key_len) :
+ NULL);
if (table_block &&
table_block->table()->engine_data() != engine_data)
@@ -3412,7 +3395,8 @@ Query_cache::insert_table(uint key_len, char *key,
*/
list_root->next= list_root->prev= list_root;
- if (my_hash_insert(&tables, (const uchar *) table_block))
+ if (hash &&
+ my_hash_insert(&tables, (const uchar *) table_block))
{
DBUG_PRINT("qcache", ("Can't insert table to hash"));
// write_block_data return locked block
@@ -3425,6 +3409,7 @@ Query_cache::insert_table(uint key_len, char *key,
header->type(cache_type);
header->callback(callback);
header->engine_data(engine_data);
+ header->set_hashed(hash);
/*
We insert this table without the assumption that it isn't refrenenced by
@@ -3478,7 +3463,9 @@ void Query_cache::unlink_table(Query_cache_block_table *node)
Query_cache_block *table_block= neighbour->block();
double_linked_list_exclude(table_block,
&tables_blocks);
- my_hash_delete(&tables,(uchar *) table_block);
+ Query_cache_table *header= table_block->table();
+ if (header->is_hashed())
+ my_hash_delete(&tables,(uchar *) table_block);
free_memory_block(table_block);
}
DBUG_VOID_RETURN;
@@ -3951,6 +3938,9 @@ Query_cache::process_and_count_tables(THD *thd, TABLE_LIST *tables_used,
table_alias_charset used here because it depends of
lower_case_table_names variable
*/
+ table_count+= tables_used->table->file->
+ count_query_cache_dependant_tables(tables_type);
+
if (tables_used->table->s->tmp_table != NO_TMP_TABLE ||
(*tables_type & HA_CACHE_TBL_NOCACHE) ||
(tables_used->db_length == 5 &&
@@ -3963,18 +3953,6 @@ Query_cache::process_and_count_tables(THD *thd, TABLE_LIST *tables_used,
"other non-cacheable table(s)"));
DBUG_RETURN(0);
}
-#ifdef WITH_MYISAMMRG_STORAGE_ENGINE
- /*
- XXX FIXME: Some generic mechanism is required here instead of this
- MYISAMMRG-specific implementation.
- */
- if (tables_used->table->s->db_type()->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);
- }
-#endif
}
}
DBUG_RETURN(table_count);
diff --git a/sql/sql_cache.h b/sql/sql_cache.h
index 87291e80a85..7444d444cf9 100644
--- a/sql/sql_cache.h
+++ b/sql/sql_cache.h
@@ -200,6 +200,10 @@ struct Query_cache_table
The number of queries depending of this table.
*/
int32 m_cached_query_count;
+ /**
+ If table included in the table hash to be found by other queries
+ */
+ my_bool hashed;
inline char *db() { return (char *) data(); }
inline char *table() { return tbl; }
@@ -212,6 +216,8 @@ struct Query_cache_table
inline void callback(qc_engine_callback fn){ callback_func= fn; }
inline ulonglong engine_data() { return engine_data_buff; }
inline void engine_data(ulonglong data_arg){ engine_data_buff= data_arg; }
+ inline my_bool is_hashed() { return hashed; }
+ inline void set_hashed(my_bool hash) { hashed= hash; }
inline uchar* data()
{
return (uchar*)(((uchar*)this)+
@@ -343,10 +349,6 @@ protected:
static void double_linked_list_join(Query_cache_block *head_tail,
Query_cache_block *tail_head);
- /* Table key generation */
- static uint filename_2_table_key (char *key, const char *filename,
- uint32 *db_langth);
-
/* The following functions require that structure_guard_mutex is locked */
void flush_cache();
my_bool free_old_query();
@@ -363,17 +365,12 @@ protected:
Query_cache_block_table *list_root);
TABLE_COUNTER_TYPE
- register_tables_from_list(TABLE_LIST *tables_used,
+ register_tables_from_list(THD *thd, TABLE_LIST *tables_used,
TABLE_COUNTER_TYPE counter,
- Query_cache_block_table *block_table);
- my_bool register_all_tables(Query_cache_block *block,
+ Query_cache_block_table **block_table);
+ my_bool register_all_tables(THD *thd, Query_cache_block *block,
TABLE_LIST *tables_used,
TABLE_COUNTER_TYPE tables);
- my_bool insert_table(uint key_len, char *key,
- Query_cache_block_table *node,
- uint32 db_length, uint8 cache_type,
- qc_engine_callback callback,
- ulonglong engine_data);
void unlink_table(Query_cache_block_table *node);
Query_cache_block *get_free_block (ulong len, my_bool not_less,
ulong min);
@@ -491,6 +488,12 @@ protected:
const char *packet,
ulong length,
unsigned pkt_nr);
+ my_bool insert_table(uint key_len, char *key,
+ Query_cache_block_table *node,
+ uint32 db_length, uint8 cache_type,
+ qc_engine_callback callback,
+ ulonglong engine_data,
+ my_bool hash);
void end_of_result(THD *thd);
void abort(Query_cache_tls *query_cache_tls);
@@ -513,6 +516,10 @@ protected:
const char *name);
my_bool in_blocks(Query_cache_block * point);
+ /* Table key generation */
+ static uint filename_2_table_key (char *key, const char *filename,
+ uint32 *db_langth);
+
enum Cache_try_lock_mode {WAIT, TIMEOUT, TRY};
bool try_lock(THD *thd, Cache_try_lock_mode mode= WAIT);
void lock(THD *thd);
diff --git a/sql/table.cc b/sql/table.cc
index 577b074a171..daccb0d1ca6 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -4551,7 +4551,14 @@ bool TABLE_LIST::check_single_table(TABLE_LIST **table_arg,
tbl;
tbl= tbl->next_local)
{
- if (tbl->table)
+ /*
+ Merged view has also temporary table attached (in 5.2 if it has table
+ then it was real table), so we have filter such temporary tables out
+ by checking that it is not merged view
+ */
+ if (tbl->table &&
+ !(tbl->is_view() &&
+ tbl->is_merged_derived()))
{
if (tbl->table->map & map)
{