diff options
author | Igor Babaev <igor@askmonty.org> | 2012-07-30 23:08:05 -0700 |
---|---|---|
committer | Igor Babaev <igor@askmonty.org> | 2012-07-30 23:08:05 -0700 |
commit | 3116e3ad6164c96edc2a27c3438f325c4dc464f3 (patch) | |
tree | a46cf41ad73a7f87c4679ea9d26d90af27b84753 /sql | |
parent | e13cd5abc1fc194eca36ed3ea145a114a3001627 (diff) | |
parent | 257fd9d3d9b5755128e0a226c26e5b5a0464b9ca (diff) | |
download | mariadb-git-3116e3ad6164c96edc2a27c3438f325c4dc464f3.tar.gz |
Merge 5.5 -> 5.5-mwl248.
Diffstat (limited to 'sql')
-rw-r--r-- | sql/ha_partition.cc | 127 | ||||
-rw-r--r-- | sql/ha_partition.h | 26 | ||||
-rw-r--r-- | sql/handler.cc | 4 | ||||
-rw-r--r-- | sql/handler.h | 42 | ||||
-rw-r--r-- | sql/item_subselect.cc | 2 | ||||
-rw-r--r-- | sql/mysql_install_db.cc | 2 | ||||
-rw-r--r-- | sql/opt_range.cc | 17 | ||||
-rw-r--r-- | sql/sql_cache.cc | 94 | ||||
-rw-r--r-- | sql/sql_cache.h | 31 | ||||
-rw-r--r-- | sql/table.cc | 9 |
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) { |