summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
Diffstat (limited to 'sql')
-rw-r--r--sql/ha_myisam.cc103
-rw-r--r--sql/ha_myisammrg.cc9
-rw-r--r--sql/handler.cc87
-rw-r--r--sql/handler.h10
-rw-r--r--sql/item.h3
-rw-r--r--sql/item_cmpfunc.h9
-rw-r--r--sql/item_func.cc5
-rw-r--r--sql/mysql_priv.h15
-rw-r--r--sql/mysqld.cc71
-rw-r--r--sql/protocol.cc13
-rw-r--r--sql/set_var.cc259
-rw-r--r--sql/set_var.h78
-rw-r--r--sql/share/czech/errmsg.txt1
-rw-r--r--sql/share/danish/errmsg.txt1
-rw-r--r--sql/share/dutch/errmsg.txt1
-rw-r--r--sql/share/english/errmsg.txt1
-rw-r--r--sql/share/estonian/errmsg.txt1
-rw-r--r--sql/share/french/errmsg.txt1
-rw-r--r--sql/share/german/errmsg.txt1
-rw-r--r--sql/share/greek/errmsg.txt1
-rw-r--r--sql/share/hungarian/errmsg.txt1
-rw-r--r--sql/share/italian/errmsg.txt1
-rw-r--r--sql/share/japanese/errmsg.txt1
-rw-r--r--sql/share/korean/errmsg.txt1
-rw-r--r--sql/share/norwegian-ny/errmsg.txt1
-rw-r--r--sql/share/norwegian/errmsg.txt1
-rw-r--r--sql/share/polish/errmsg.txt1
-rw-r--r--sql/share/portuguese/errmsg.txt1
-rw-r--r--sql/share/romanian/errmsg.txt1
-rw-r--r--sql/share/russian/errmsg.txt1
-rw-r--r--sql/share/serbian/errmsg.txt1
-rw-r--r--sql/share/slovak/errmsg.txt1
-rw-r--r--sql/share/spanish/errmsg.txt1
-rw-r--r--sql/share/swedish/errmsg.txt1
-rw-r--r--sql/share/ukrainian/errmsg.txt1
-rw-r--r--sql/sql_base.cc160
-rw-r--r--sql/sql_db.cc36
-rw-r--r--sql/sql_delete.cc5
-rw-r--r--sql/sql_lex.cc2
-rw-r--r--sql/sql_lex.h2
-rw-r--r--sql/sql_parse.cc58
-rw-r--r--sql/sql_show.cc7
-rw-r--r--sql/sql_table.cc125
-rw-r--r--sql/sql_test.cc81
-rw-r--r--sql/sql_yacc.yy71
-rw-r--r--sql/structs.h2
-rw-r--r--sql/table.cc6
-rw-r--r--sql/table.h30
-rw-r--r--sql/unireg.h15
49 files changed, 599 insertions, 686 deletions
diff --git a/sql/ha_myisam.cc b/sql/ha_myisam.cc
index 52a5398bdd8..0f22a83a2b4 100644
--- a/sql/ha_myisam.cc
+++ b/sql/ha_myisam.cc
@@ -226,15 +226,10 @@ err:
int ha_myisam::open(const char *name, int mode, uint test_if_locked)
{
+ KEY_CACHE_VAR *key_cache;
if (!(file=mi_open(name, mode, test_if_locked)))
return (my_errno ? my_errno : -1);
- /* Synchronize key cache assignment of the handler */
- KEY_CACHE_VAR *key_cache= table->key_cache ? table->key_cache :
- &dflt_key_cache_var;
- VOID(mi_extra(file, HA_EXTRA_SET_KEY_CACHE,
- (void*) &key_cache->cache));
-
if (test_if_locked & (HA_OPEN_IGNORE_IF_LOCKED | HA_OPEN_TMP_TABLE))
VOID(mi_extra(file, HA_EXTRA_NO_WAIT_LOCK, 0));
info(HA_STATUS_NO_LOCK | HA_STATUS_VARIABLE | HA_STATUS_CONST);
@@ -698,93 +693,48 @@ int ha_myisam::repair(THD *thd, MI_CHECK &param, bool optimize)
/*
- Assign table indexes to a key cache.
+ Assign table indexes to a specific key cache.
*/
int ha_myisam::assign_to_keycache(THD* thd, HA_CHECK_OPT *check_opt)
{
- uint len;
- KEY_CACHE_VAR *old_key_cache;
- KEY_CACHE_VAR *new_key_cache;
- const char *errmsg=0;
+ KEY_CACHE_VAR *new_key_cache= check_opt->key_cache;
+ const char *errmsg= 0;
int error= HA_ADMIN_OK;
ulonglong map= ~(ulonglong) 0;
TABLE_LIST *table_list= table->pos_in_table_list;
- const char *new_key_cache_name= table_list->option ?
- (const char *) table_list->option :
- DEFAULT_KEY_CACHE_NAME;
- KEY_CACHE_ASMT *key_cache_asmt= table->key_cache_asmt;
- bool triggered= key_cache_asmt->triggered;
-
DBUG_ENTER("ha_myisam::assign_to_keycache");
- VOID(pthread_mutex_lock(&LOCK_assign));
-
- old_key_cache= key_cache_asmt->key_cache;
-
/* Check validity of the index references */
- if (!triggered && table_list->use_index)
+ if (table_list->use_index)
{
+ /* We only come here when the user did specify an index map */
key_map kmap;
- get_key_map_from_key_list(&kmap, table, table_list->use_index);
- if (kmap.is_set_all())
+ if (get_key_map_from_key_list(&kmap, table, table_list->use_index))
{
errmsg= thd->net.last_error;
error= HA_ADMIN_FAILED;
goto err;
}
- if (!kmap.is_clear_all())
- map= kmap.to_ulonglong();
- }
-
- len= strlen(new_key_cache_name);
- new_key_cache= get_or_create_key_cache(new_key_cache_name, len);
- if (old_key_cache == new_key_cache)
- {
- /* Nothing to do: table is assigned to the same key cache */
- goto ok;
- }
-
- if (!new_key_cache ||
- (!new_key_cache->cache && ha_key_cache(new_key_cache)))
- {
- if (key_cache_asmt->triggered)
- error= HA_ERR_OUT_OF_MEM;
- else
- {
- char buf[ERRMSGSIZE];
- my_snprintf(buf, ERRMSGSIZE,
- "Failed to create key cache %s", new_key_cache_name);
- errmsg= buf;
- error= HA_ADMIN_FAILED;
- }
- goto err;
+ map= kmap.to_ulonglong();
}
- reassign_key_cache(key_cache_asmt, new_key_cache);
-
- VOID(pthread_mutex_unlock(&LOCK_assign));
- error= mi_assign_to_keycache(file, map, new_key_cache, &LOCK_assign);
- VOID(pthread_mutex_lock(&LOCK_assign));
-
- if (error && !key_cache_asmt->triggered)
+ if ((error= mi_assign_to_key_cache(file, map, new_key_cache)))
{
switch (error) {
default:
- char buf[ERRMSGSIZE+20];
- my_snprintf(buf, ERRMSGSIZE,
- "Failed to flush to index file (errno: %d)", my_errno);
+ char buf[80];
+ my_snprintf(buf, sizeof(buf),
+ "Failed to flush to index file (errno: %d)", error);
errmsg= buf;
}
error= HA_ADMIN_CORRUPT;
- goto err;
}
- goto ok;
-
err:
- if (!triggered)
+ if (error != HA_ADMIN_OK)
{
+ /* Send error to user */
MI_CHECK param;
myisamchk_init(&param);
param.thd= thd;
@@ -793,32 +743,7 @@ int ha_myisam::assign_to_keycache(THD* thd, HA_CHECK_OPT *check_opt)
param.table_name= table->table_name;
param.testflag= 0;
mi_check_print_error(&param, errmsg);
- }
-
- ok:
- if (--key_cache_asmt->requests)
- {
- /* There is a queue of assignments for the table */
-
- /* Remove the first member from the queue */
- struct st_my_thread_var *last= key_cache_asmt->queue;
- struct st_my_thread_var *thread= last->next;
- if (thread->next == thread)
- key_cache_asmt->queue= 0;
- else
- {
- last->next= thread->next;
- last->next->prev= &last->next;
- thread->next= 0;
- }
- /* Signal the first waiting thread to proceed */
- VOID(pthread_cond_signal(&thread->suspend));
}
-
- key_cache_asmt->triggered= 0;
-
- VOID(pthread_mutex_unlock(&LOCK_assign));
-
DBUG_RETURN(error);
}
diff --git a/sql/ha_myisammrg.cc b/sql/ha_myisammrg.cc
index 05da214c1d4..a834ace7032 100644
--- a/sql/ha_myisammrg.cc
+++ b/sql/ha_myisammrg.cc
@@ -35,9 +35,12 @@
const char **ha_myisammrg::bas_ext() const
{ static const char *ext[]= { ".MRG", NullS }; return ext; }
+
int ha_myisammrg::open(const char *name, int mode, uint test_if_locked)
{
char name_buff[FN_REFLEN];
+ KEY_CACHE_VAR *key_cache;
+
DBUG_PRINT("info", ("ha_myisammrg::open"));
if (!(file=myrg_open(fn_format(name_buff,name,"","",2 | 4), mode,
test_if_locked)))
@@ -45,12 +48,6 @@ int ha_myisammrg::open(const char *name, int mode, uint test_if_locked)
DBUG_PRINT("info", ("ha_myisammrg::open exit %d", my_errno));
return (my_errno ? my_errno : -1);
}
- /* Synchronize key cache assignment for the file */
- KEY_CACHE_VAR *key_cache= table->key_cache ? table->key_cache :
- &dflt_key_cache_var;
- VOID(myrg_extra(file, HA_EXTRA_SET_KEY_CACHE,
- (void*) &key_cache->cache));
-
DBUG_PRINT("info", ("ha_myisammrg::open myrg_extrafunc..."))
myrg_extrafunc(file, query_cache_invalidate_by_MyISAM_filename_ref);
if (!(test_if_locked == HA_OPEN_WAIT_IF_LOCKED ||
diff --git a/sql/handler.cc b/sql/handler.cc
index 28f399818c4..56db355f45e 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -1105,76 +1105,97 @@ int ha_create_table(const char *name, HA_CREATE_INFO *create_info,
DBUG_RETURN(error != 0);
}
- /* Use key cacheing on all databases */
+static int NEAR_F delete_file(const char *name,const char *ext,int extflag)
+{
+ char buff[FN_REFLEN];
+ VOID(fn_format(buff,name,"",ext,extflag | 4));
+ return(my_delete_with_symlink(buff,MYF(MY_WME)));
+}
+
+void st_ha_check_opt::init()
+{
+ flags= sql_flags= 0;
+ sort_buffer_size = current_thd->variables.myisam_sort_buff_size;
+}
+
+
+/*****************************************************************************
+ Key cache handling.
+
+ This code is only relevant for ISAM/MyISAM tables
+
+ key_cache->cache may be 0 only in the case where a key cache is not
+ initialized or when we where not able to init the key cache in a previous
+ call to ha_init_key_cache() (probably out of memory)
+*****************************************************************************/
+
+/* Init a key cache if it has not been initied before */
-int ha_key_cache(KEY_CACHE_VAR *key_cache)
+
+int ha_init_key_cache(const char *name, KEY_CACHE_VAR *key_cache)
{
+ DBUG_ENTER("ha_init_key_cache");
+
if (!key_cache->cache)
{
- /*
- The following mutex is not really needed as long as keybuff_size is
- treated as a long value, but we use the mutex here to guard for future
- changes.
- */
pthread_mutex_lock(&LOCK_global_system_variables);
- if (!key_cache->block_size)
- key_cache->block_size= dflt_key_cache_block_size;
- if (!key_cache->buff_size)
- key_cache->buff_size= dflt_key_buff_size;
long tmp_buff_size= (long) key_cache->buff_size;
long tmp_block_size= (long) key_cache->block_size;
pthread_mutex_unlock(&LOCK_global_system_variables);
- return !init_key_cache(&key_cache->cache,
- tmp_block_size,
- tmp_buff_size,
- key_cache);
+ DBUG_RETURN(!init_key_cache(&key_cache->cache,
+ tmp_block_size,
+ tmp_buff_size,
+ key_cache));
}
- return 0;
+ DBUG_RETURN(0);
}
+
+/* Resize key cache */
+
int ha_resize_key_cache(KEY_CACHE_VAR *key_cache)
{
+ DBUG_ENTER("ha_resize_key_cache");
+
if (key_cache->cache)
{
pthread_mutex_lock(&LOCK_global_system_variables);
long tmp_buff_size= (long) key_cache->buff_size;
long tmp_block_size= (long) key_cache->block_size;
pthread_mutex_unlock(&LOCK_global_system_variables);
- return !resize_key_cache(&key_cache->cache, tmp_block_size,
- tmp_buff_size);
+ DBUG_RETURN(!resize_key_cache(&key_cache->cache, tmp_block_size,
+ tmp_buff_size));
}
- return 0;
+ DBUG_RETURN(0);
}
+
+/* Change parameters for key cache (like size) */
+
int ha_change_key_cache_param(KEY_CACHE_VAR *key_cache)
{
if (key_cache->cache)
- {
change_key_cache_param(key_cache->cache);
- }
return 0;
}
+/* Free memory allocated by a key cache */
+
int ha_end_key_cache(KEY_CACHE_VAR *key_cache)
{
if (key_cache->cache)
{
- end_key_cache(&key_cache->cache, 1);
- return key_cache->cache ? 1 : 0;
+ end_key_cache(key_cache->cache, 1); // Can never fail
+ key_cache->cache= 0;
}
return 0;
}
+/* Move all tables from one key cache to another one */
-static int NEAR_F delete_file(const char *name,const char *ext,int extflag)
+int ha_change_key_cache(KEY_CACHE_VAR *old_key_cache,
+ KEY_CACHE_VAR *new_key_cache)
{
- char buff[FN_REFLEN];
- VOID(fn_format(buff,name,"",ext,extflag | 4));
- return(my_delete_with_symlink(buff,MYF(MY_WME)));
-}
-
-void st_ha_check_opt::init()
-{
- flags= sql_flags= 0;
- sort_buffer_size = current_thd->variables.myisam_sort_buff_size;
+ mi_change_key_cache(old_key_cache, new_key_cache);
+ return 0;
}
diff --git a/sql/handler.h b/sql/handler.h
index c24bf777f01..40773c67605 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -145,6 +145,7 @@ enum row_type { ROW_TYPE_NOT_USED=-1, ROW_TYPE_DEFAULT, ROW_TYPE_FIXED,
#define HA_CREATE_USED_AVG_ROW_LENGTH 64
#define HA_CREATE_USED_PACK_KEYS 128
#define HA_CREATE_USED_CHARSET 256
+#define HA_CREATE_USED_DEFAULT_CHARSET 512
typedef struct st_thd_trans {
void *bdb_tid;
@@ -157,7 +158,7 @@ enum enum_tx_isolation { ISO_READ_UNCOMMITTED, ISO_READ_COMMITTED,
typedef struct st_ha_create_information
{
- CHARSET_INFO *table_charset;
+ CHARSET_INFO *table_charset, *default_table_charset;
char *comment,*password;
char *data_file_name, *index_file_name;
ulonglong max_rows,min_rows;
@@ -180,15 +181,18 @@ typedef struct st_ha_create_information
struct st_table;
typedef struct st_table TABLE;
+typedef struct st_key_cache_asmt KEY_CACHE_ASMT;
typedef struct st_ha_check_opt
{
ulong sort_buffer_size;
uint flags; /* isam layer flags (e.g. for myisamchk) */
uint sql_flags; /* sql layer flags - for something myisamchk cannot do */
+ KEY_CACHE_VAR *key_cache; /* new key cache when changing key cache */
void init();
} HA_CHECK_OPT;
+
class handler :public Sql_alloc
{
protected:
@@ -390,7 +394,7 @@ int ha_create_table(const char *name, HA_CREATE_INFO *create_info,
bool update_create_info);
int ha_delete_table(enum db_type db_type, const char *path);
void ha_drop_database(char* path);
-int ha_key_cache(KEY_CACHE_VAR *key_cache);
+int ha_init_key_cache(const char *name, KEY_CACHE_VAR *key_cache);
int ha_resize_key_cache(KEY_CACHE_VAR *key_cache);
int ha_change_key_cache_param(KEY_CACHE_VAR *key_cache);
int ha_end_key_cache(KEY_CACHE_VAR *key_cache);
@@ -407,3 +411,5 @@ int ha_autocommit_or_rollback(THD *thd, int error);
void ha_set_spin_retries(uint retries);
bool ha_flush_logs(void);
int ha_recovery_logging(THD *thd, bool on);
+int ha_change_key_cache(KEY_CACHE_VAR *old_key_cache,
+ KEY_CACHE_VAR *new_key_cache);
diff --git a/sql/item.h b/sql/item.h
index f473ca33676..8b35705f191 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -125,9 +125,10 @@ public:
optimisation changes in prepared statements
*/
Item(THD *thd, Item &item);
- virtual ~Item() { name=0; } /*lint -e1509 */
+ virtual ~Item() { name=0; cleanup(); } /*lint -e1509 */
void set_name(const char *str,uint length, CHARSET_INFO *cs);
void init_make_field(Send_field *tmp_field,enum enum_field_types type);
+ virtual void cleanup() {}
virtual void make_field(Send_field *field);
virtual bool fix_fields(THD *, struct st_table_list *, Item **);
virtual int save_in_field(Field *field, bool no_conversions);
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index 081374345d8..dac7a2d43eb 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -715,7 +715,14 @@ class Item_func_in :public Item_int_func
}
longlong val_int();
void fix_length_and_dec();
- ~Item_func_in() { delete array; delete in_item; }
+ ~Item_func_in() {}
+ void cleanup()
+ {
+ delete array;
+ delete in_item;
+ array= 0;
+ in_item= 0;
+ }
optimize_type select_optimize() const
{ return array ? OPTIMIZE_KEY : OPTIMIZE_NONE; }
void print(String *str);
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 43cc67b554e..78486cb855d 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -2648,6 +2648,8 @@ err:
void Item_func_match::init_search(bool no_order)
{
DBUG_ENTER("Item_func_match::init_search");
+
+ /* Check if init_search() has been called before */
if (ft_handler)
DBUG_VOID_RETURN;
@@ -2685,7 +2687,8 @@ void Item_func_match::init_search(bool no_order)
ft_tmp= &search_value;
}
- if (join_key && !no_order) flags|=FT_SORTED;
+ if (join_key && !no_order)
+ flags|=FT_SORTED;
ft_handler=table->file->ft_init_ext(flags, key,
(byte*) ft_tmp->ptr(),
ft_tmp->length());
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index 71ad5ce67c2..ff3b7291965 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -427,8 +427,6 @@ bool check_stack_overrun(THD *thd,char *dummy);
void table_cache_init(void);
void table_cache_free(void);
uint cached_tables(void);
-void assign_cache_init(void);
-void assign_cache_free(void);
void reassign_key_cache(KEY_CACHE_ASMT *key_cache_asmt,
KEY_CACHE_VAR *new_key_cache);
void kill_mysql(void);
@@ -460,10 +458,11 @@ int mysql_analyze_table(THD* thd, TABLE_LIST* table_list,
HA_CHECK_OPT* check_opt);
int mysql_optimize_table(THD* thd, TABLE_LIST* table_list,
HA_CHECK_OPT* check_opt);
-int mysql_assign_to_keycache(THD* thd, TABLE_LIST* table_list);
+int mysql_assign_to_keycache(THD* thd, TABLE_LIST* table_list,
+ LEX_STRING *key_cache_name);
int mysql_preload_keys(THD* thd, TABLE_LIST* table_list);
-int reassign_keycache_tables(THD* thd, KEY_CACHE_VAR* src_cache,
- char *dest_name, bool remove_fl);
+int reassign_keycache_tables(THD* thd, KEY_CACHE_VAR *src_cache,
+ KEY_CACHE_VAR *dst_cache);
bool check_simple_select();
@@ -662,7 +661,7 @@ enum find_item_error_report_type {REPORT_ALL_ERRORS, REPORT_EXCEPT_NOT_FOUND,
extern const Item **not_found_item;
Item ** find_item_in_list(Item *item, List<Item> &items, uint *counter,
find_item_error_report_type report_error);
-void get_key_map_from_key_list(key_map *map, TABLE *table,
+bool get_key_map_from_key_list(key_map *map, TABLE *table,
List<String> *index_list);
bool insert_fields(THD *thd,TABLE_LIST *tables,
const char *db_name, const char *table_name,
@@ -849,7 +848,7 @@ extern pthread_mutex_t LOCK_mysql_create_db,LOCK_Acl,LOCK_open,
LOCK_error_log, LOCK_delayed_insert,
LOCK_delayed_status, LOCK_delayed_create, LOCK_crypt, LOCK_timezone,
LOCK_slave_list, LOCK_active_mi, LOCK_manager,
- LOCK_global_system_variables, LOCK_user_conn, LOCK_assign;
+ LOCK_global_system_variables, LOCK_user_conn;
extern rw_lock_t LOCK_grant;
extern pthread_cond_t COND_refresh, COND_thread_count, COND_manager;
extern pthread_attr_t connection_attrib;
@@ -866,6 +865,8 @@ extern SHOW_COMP_OPTION have_berkeley_db;
extern struct system_variables global_system_variables;
extern struct system_variables max_system_variables;
extern struct rand_struct sql_rand;
+extern KEY_CACHE_VAR *sql_key_cache;
+extern KEY_CACHE_HANDLE sql_key_cache_handle;
extern const char *opt_date_time_formats[];
extern KNOWN_DATE_TIME_FORMAT known_date_time_formats[];
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index a4c51321e97..f26f18418a8 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -355,6 +355,7 @@ struct system_variables max_system_variables;
MY_TMPDIR mysql_tmpdir_list;
MY_BITMAP temp_pool;
+KEY_CACHE_VAR *sql_key_cache;
CHARSET_INFO *system_charset_info, *files_charset_info ;
CHARSET_INFO *national_charset_info, *table_alias_charset;
@@ -373,7 +374,6 @@ pthread_mutex_t LOCK_mysql_create_db, LOCK_Acl, LOCK_open, LOCK_thread_count,
LOCK_delayed_insert, LOCK_delayed_status, LOCK_delayed_create,
LOCK_crypt, LOCK_bytes_sent, LOCK_bytes_received,
LOCK_global_system_variables,
- LOCK_assign,
LOCK_user_conn, LOCK_slave_list, LOCK_active_mi;
rw_lock_t LOCK_grant;
pthread_cond_t COND_refresh,COND_thread_count, COND_slave_stopped,
@@ -900,7 +900,6 @@ void clean_up(bool print_message)
#endif
query_cache_destroy();
table_cache_free();
- assign_cache_free();
hostname_cache_free();
item_user_lock_free();
lex_free(); /* Free some memory */
@@ -910,9 +909,8 @@ void clean_up(bool print_message)
udf_free();
#endif
(void) ha_panic(HA_PANIC_CLOSE); /* close all tables and logs */
- process_key_caches(&ha_end_key_cache);
- ha_end_key_cache(&dflt_key_cache_var);
- delete_elements(&key_caches, free_key_cache);
+ delete_elements(&key_caches, (void (*)(const char*, gptr)) free_key_cache);
+ multi_keycache_free();
end_thr_alarm(1); /* Free allocated memory */
#ifdef USE_RAID
end_raid();
@@ -997,7 +995,6 @@ static void clean_up_mutexes()
#endif
(void) pthread_mutex_destroy(&LOCK_active_mi);
(void) pthread_mutex_destroy(&LOCK_global_system_variables);
- (void) pthread_mutex_destroy(&LOCK_assign);
(void) pthread_cond_destroy(&COND_thread_count);
(void) pthread_cond_destroy(&COND_refresh);
(void) pthread_cond_destroy(&COND_thread_cache);
@@ -1568,14 +1565,14 @@ We will try our best to scrape up some info that will hopefully help diagnose\n\
the problem, but since we have already crashed, something is definitely wrong\n\
and this may fail.\n\n");
fprintf(stderr, "key_buffer_size=%lu\n",
- (ulong) dflt_key_cache_var.buff_size);
+ (ulong) sql_key_cache->buff_size);
fprintf(stderr, "read_buffer_size=%ld\n", global_system_variables.read_buff_size);
fprintf(stderr, "max_used_connections=%ld\n", max_used_connections);
fprintf(stderr, "max_connections=%ld\n", max_connections);
fprintf(stderr, "threads_connected=%d\n", thread_count);
fprintf(stderr, "It is possible that mysqld could use up to \n\
key_buffer_size + (read_buffer_size + sort_buffer_size)*max_connections = %ld K\n\
-bytes of memory\n", ((ulong) dflt_key_cache_var.buff_size +
+bytes of memory\n", ((ulong) sql_key_cache->buff_size +
(global_system_variables.read_buff_size +
global_system_variables.sortbuff_size) *
max_connections)/ 1024);
@@ -2204,7 +2201,6 @@ static int init_thread_environment()
(void) pthread_mutex_init(&LOCK_user_conn, MY_MUTEX_INIT_FAST);
(void) pthread_mutex_init(&LOCK_active_mi, MY_MUTEX_INIT_FAST);
(void) pthread_mutex_init(&LOCK_global_system_variables, MY_MUTEX_INIT_FAST);
- (void) pthread_mutex_init(&LOCK_assign, MY_MUTEX_INIT_FAST);
(void) my_rwlock_init(&LOCK_grant, NULL);
(void) pthread_cond_init(&COND_thread_count,NULL);
(void) pthread_cond_init(&COND_refresh,NULL);
@@ -2256,7 +2252,6 @@ static int init_server_components()
{
DBUG_ENTER("init_server_components");
table_cache_init();
- assign_cache_init();
hostname_cache_init();
query_cache_result_size_limit(query_cache_limit);
query_cache_set_min_res_unit(query_cache_min_res_unit);
@@ -2328,9 +2323,10 @@ Now disabling --log-slave-updates.");
if (opt_myisam_log)
(void) mi_log(1);
- ha_key_cache(&dflt_key_cache_var);
- process_key_caches(&ha_key_cache);
-
+ /* call ha_init_key_cache() on all key caches to init them */
+ process_key_caches(&ha_init_key_cache);
+ /* We must set dflt_key_cache in case we are using ISAM tables */
+ dflt_keycache= &sql_key_cache->cache;
#if defined(HAVE_MLOCKALL) && defined(MCL_CURRENT)
if (locked_in_memory && !geteuid())
@@ -4321,25 +4317,28 @@ replicating a LOAD DATA INFILE command.",
{"key_buffer_size", OPT_KEY_BUFFER_SIZE,
"The size of the buffer used for index blocks for MyISAM tables. Increase this to get better index handling (for all reads and multiple writes) to as much as you can afford; 64M on a 256M machine that mainly runs MySQL is quite common.",
(gptr*) &dflt_key_cache_var.buff_size,
- (gptr*) &dflt_key_cache_var.buff_size, 0,
- (enum get_opt_var_type) (GET_ULL | GET_ASK_ADDR),
+ (gptr*) 0,
+ 0, (enum get_opt_var_type) (GET_ULL | GET_ASK_ADDR),
REQUIRED_ARG, KEY_CACHE_SIZE, MALLOC_OVERHEAD, (long) ~0, MALLOC_OVERHEAD,
IO_SIZE, 0},
{"key_cache_block_size", OPT_KEY_CACHE_BLOCK_SIZE,
"The default size of key cache blocks",
(gptr*) &dflt_key_cache_var.block_size,
- (gptr*) &dflt_key_cache_var.block_size, 0, GET_ULONG,
- REQUIRED_ARG, KEY_CACHE_BLOCK_SIZE , 512, 1024*16, MALLOC_OVERHEAD, 512, 0},
+ (gptr*) 0,
+ 0, (enum get_opt_var_type) (GET_ULONG | GET_ASK_ADDR), REQUIRED_ARG,
+ KEY_CACHE_BLOCK_SIZE , 512, 1024*16, MALLOC_OVERHEAD, 512, 0},
{"key_cache_division_limit", OPT_KEY_CACHE_DIVISION_LIMIT,
"The minimum percentage of warm blocks in key cache",
(gptr*) &dflt_key_cache_var.division_limit,
- (gptr*) &dflt_key_cache_var.division_limit, 0, GET_ULONG,
- REQUIRED_ARG, 100, 1, 100, 0, 1, 0},
+ (gptr*) 0,
+ 0, (enum get_opt_var_type) (GET_ULONG | GET_ASK_ADDR) , REQUIRED_ARG, 100,
+ 1, 100, 0, 1, 0},
{"key_cache_division_age_threshold", OPT_KEY_CACHE_AGE_THRESHOLD,
"This characterizes the number of hits a hot block has to be untouched until it is considered aged enough to be downgraded to a warm block. This specifies the percentage ratio of that number of hits to the total number of blocks in key cache",
(gptr*) &dflt_key_cache_var.age_threshold,
- (gptr*) &dflt_key_cache_var.age_threshold, 0, GET_ULONG,
- REQUIRED_ARG, 300, 100, ~0L, 0, 100, 0},
+ (gptr*) 0,
+ 0, (enum get_opt_var_type) (GET_ULONG | GET_ASK_ADDR), REQUIRED_ARG,
+ 300, 100, ~0L, 0, 100, 0},
{"long_query_time", OPT_LONG_QUERY_TIME,
"Log all queries that have taken more than long_query_time seconds to execute to file.",
(gptr*) &global_system_variables.long_query_time,
@@ -4758,19 +4757,19 @@ struct show_var_st status_vars[]= {
{"Handler_rollback", (char*) &ha_rollback_count, SHOW_LONG},
{"Handler_update", (char*) &ha_update_count, SHOW_LONG},
{"Handler_write", (char*) &ha_write_count, SHOW_LONG},
+ {"Key_blocks_not_flushed", (char*) &dflt_key_cache_var.blocks_changed,
+ SHOW_KEY_CACHE_LONG},
{"Key_blocks_used", (char*) &dflt_key_cache_var.blocks_used,
- SHOW_LONG_CONST},
+ SHOW_KEY_CACHE_LONG},
{"Key_read_requests", (char*) &dflt_key_cache_var.cache_r_requests,
- SHOW_LONG},
+ SHOW_KEY_CACHE_LONG},
{"Key_reads", (char*) &dflt_key_cache_var.cache_read,
- SHOW_LONG},
+ SHOW_KEY_CACHE_LONG},
{"Key_write_requests", (char*) &dflt_key_cache_var.cache_w_requests,
- SHOW_LONG},
+ SHOW_KEY_CACHE_LONG},
{"Key_writes", (char*) &dflt_key_cache_var.cache_write,
- SHOW_LONG},
+ SHOW_KEY_CACHE_LONG},
{"Max_used_connections", (char*) &max_used_connections, SHOW_LONG},
- {"Not_flushed_key_blocks", (char*) &dflt_key_cache_var.blocks_changed,
- SHOW_LONG_CONST},
{"Not_flushed_delayed_rows", (char*) &delayed_rows_in_use, SHOW_LONG_CONST},
{"Open_tables", (char*) 0, SHOW_OPENTABLES},
{"Open_files", (char*) &my_file_opened, SHOW_LONG_CONST},
@@ -4984,8 +4983,9 @@ static void mysql_init_variables(void)
threads.empty();
thread_cache.empty();
key_caches.empty();
- if (!get_or_create_key_cache(DEFAULT_KEY_CACHE_NAME,
- strlen(DEFAULT_KEY_CACHE_NAME)))
+ multi_keycache_init();
+ if (!(sql_key_cache= get_or_create_key_cache(default_key_cache_base.str,
+ default_key_cache_base.length)))
exit(1);
/* Initialize structures that is used when processing options */
@@ -5075,9 +5075,9 @@ static void mysql_init_variables(void)
have_crypt=SHOW_OPTION_NO;
#endif
#ifdef HAVE_COMPRESS
- SHOW_COMP_OPTION have_compress= SHOW_OPTION_YES;
+ have_compress= SHOW_OPTION_YES;
#else
- SHOW_COMP_OPTION have_compress= SHOW_OPTION_NO;
+ have_compress= SHOW_OPTION_NO;
#endif
#ifdef HAVE_LIBWRAP
libwrapName= NullS;
@@ -5699,13 +5699,6 @@ static void get_options(int argc,char **argv)
init_global_datetime_format(TIMESTAMP_DATETIME,
&global_system_variables.datetime_format))
exit(1);
-
- /* Set up default values for a key cache */
- KEY_CACHE_VAR *key_cache= &dflt_key_cache_var;
- dflt_key_cache_block_size= key_cache->block_size;
- dflt_key_buff_size= key_cache->buff_size;
- dflt_key_cache_division_limit= key_cache->division_limit;
- dflt_key_cache_age_threshold= key_cache->age_threshold;
}
diff --git a/sql/protocol.cc b/sql/protocol.cc
index 8ba3cdec8e0..884569d334a 100644
--- a/sql/protocol.cc
+++ b/sql/protocol.cc
@@ -120,6 +120,10 @@ void send_error(THD *thd, uint sql_errno, const char *err)
#endif /* EMBEDDED_LIBRARY*/
thd->is_fatal_error=0; // Error message is given
thd->net.report_error= 0;
+
+ /* Abort multi-result sets */
+ thd->lex.found_colon= 0;
+ thd->server_status= ~SERVER_MORE_RESULTS_EXISTS;
DBUG_VOID_RETURN;
}
@@ -338,7 +342,14 @@ send_eof(THD *thd, bool no_flush)
uint tmp= min(thd->total_warn_count, 65535);
buff[0]=254;
int2store(buff+1, tmp);
- int2store(buff+3, 0); // No flags yet
+ /*
+ The following test should never be true, but it's better to do it
+ because if 'is_fatal_error' is set the server is not going to execute
+ other queries (see the if test in dispatch_command / COM_QUERY)
+ */
+ if (thd->is_fatal_error)
+ thd->server_status= ~SERVER_MORE_RESULTS_EXISTS;
+ int2store(buff+3, thd->server_status);
VOID(my_net_write(net,(char*) buff,5));
VOID(net_flush(net));
}
diff --git a/sql/set_var.cc b/sql/set_var.cc
index 76fb2e0a4b3..9a4543ada00 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -60,11 +60,6 @@
#include "ha_innodb.h"
#endif
-ulonglong dflt_key_buff_size;
-uint dflt_key_cache_block_size;
-uint dflt_key_cache_division_limit;
-uint dflt_key_cache_age_threshold;
-
static HASH system_variable_hash;
const char *bool_type_names[]= { "OFF", "ON", NullS };
TYPELIB bool_typelib=
@@ -148,11 +143,15 @@ sys_var_thd_ulong sys_interactive_timeout("interactive_timeout",
sys_var_thd_ulong sys_join_buffer_size("join_buffer_size",
&SV::join_buff_size);
sys_var_key_buffer_size sys_key_buffer_size("key_buffer_size");
-sys_var_key_cache_block_size sys_key_cache_block_size("key_cache_block_size");
-sys_var_key_cache_division_limit
- sys_key_cache_division_limit("key_cache_division_limit");
-sys_var_key_cache_age_threshold
- sys_key_cache_age_threshold("key_cache_age_threshold");
+sys_var_key_cache_long sys_key_cache_block_size("key_cache_block_size",
+ offsetof(KEY_CACHE_VAR,
+ block_size));
+sys_var_key_cache_long sys_key_cache_division_limit("key_cache_division_limit",
+ offsetof(KEY_CACHE_VAR,
+ division_limit));
+sys_var_key_cache_long sys_key_cache_age_threshold("key_cache_age_threshold",
+ offsetof(KEY_CACHE_VAR,
+ age_threshold));
sys_var_bool_ptr sys_local_infile("local_infile",
&opt_local_infile);
sys_var_thd_bool sys_log_warnings("log_warnings", &SV::log_warnings);
@@ -1266,7 +1265,13 @@ Item *sys_var::item(THD *thd, enum_var_type var_type, LEX_STRING *base)
}
switch (type()) {
case SHOW_LONG:
- return new Item_uint((int32) *(ulong*) value_ptr(thd, var_type, base));
+ {
+ ulong value;
+ pthread_mutex_lock(&LOCK_global_system_variables);
+ value= *(ulong*) value_ptr(thd, var_type, base);
+ pthread_mutex_unlock(&LOCK_global_system_variables);
+ return new Item_uint((int32) value);
+ }
case SHOW_LONGLONG:
{
longlong value;
@@ -1771,24 +1776,21 @@ void sys_var_collation_server::set_default(THD *thd, enum_var_type type)
}
-static LEX_STRING default_key_cache_base= {(char *) DEFAULT_KEY_CACHE_NAME, 7};
+LEX_STRING default_key_cache_base= {(char *) "default", 7 };
static KEY_CACHE_VAR zero_key_cache=
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
-static KEY_CACHE_VAR *get_key_cache(LEX_STRING *cache_name)
+KEY_CACHE_VAR *get_key_cache(LEX_STRING *cache_name)
{
- if (!cache_name || !cache_name->str || !cache_name->length ||
- cache_name->str == default_key_cache_base.str ||
- (cache_name->length == default_key_cache_base.length &&
- !memcmp(cache_name->str, default_key_cache_base.str,
- default_key_cache_base.length)))
+ safe_mutex_assert_owner(&LOCK_global_system_variables);
+ if (!cache_name || ! cache_name->length)
cache_name= &default_key_cache_base;
return ((KEY_CACHE_VAR*) find_named(&key_caches,
- cache_name->str, cache_name->length,
- 0));
+ cache_name->str, cache_name->length, 0));
}
+
byte *sys_var_key_cache_param::value_ptr(THD *thd, enum_var_type type,
LEX_STRING *base)
{
@@ -1798,115 +1800,134 @@ byte *sys_var_key_cache_param::value_ptr(THD *thd, enum_var_type type,
return (byte*) key_cache + offset ;
}
+
bool sys_var_key_buffer_size::update(THD *thd, set_var *var)
{
ulonglong tmp= var->save_result.ulonglong_value;
-
LEX_STRING *base_name= &var->base;
+ KEY_CACHE_VAR *key_cache;
+ bool error= 0;
+
+ /* If no basename, assume it's for the key cache named 'default' */
if (!base_name->length)
base_name= &default_key_cache_base;
- KEY_CACHE_VAR *key_cache= get_key_cache(base_name);
+
+ pthread_mutex_lock(&LOCK_global_system_variables);
+ key_cache= get_key_cache(base_name);
if (!key_cache)
{
+ /* Key cache didn't exists */
if (!tmp) // Tried to delete cache
- return 0; // Ok, nothing to do
- if (!(key_cache= create_key_cache(base_name->str,
- base_name->length)))
- return 1;
+ goto end; // Ok, nothing to do
+ if (!(key_cache= create_key_cache(base_name->str, base_name->length)))
+ {
+ error= 1;
+ goto end;
+ }
}
+
+ /*
+ Abort if some other thread is changing the key cache
+ TODO: This should be changed so that we wait until the previous
+ assignment is done and then do the new assign
+ */
+ if (key_cache->in_init)
+ goto end;
+
if (!tmp) // Zero size means delete
{
- if (!key_cache->cache)
- return 0;
- /* Delete not default key caches */
- if (key_cache != &dflt_key_cache_var)
+ if (key_cache == sql_key_cache)
+ goto end; // Ignore default key cache
+
+ if (key_cache->cache) // If initied
{
/*
- Move tables using this key cache to the default key cache
- and remove this key cache if no tables are assigned to it
+ Move tables using this key cache to the default key cache
+ and clear the old key cache.
*/
NAMED_LIST *list;
key_cache= (KEY_CACHE_VAR *) find_named(&key_caches, base_name->str,
base_name->length, &list);
- delete list;
- int rc= reassign_keycache_tables(thd, key_cache,
- default_key_cache_base.str, 1);
- my_free((char*) key_cache, MYF(0));
- return rc;
-
+ key_cache->in_init= 1;
+ pthread_mutex_unlock(&LOCK_global_system_variables);
+ error= reassign_keycache_tables(thd, key_cache, sql_key_cache);
+ pthread_mutex_lock(&LOCK_global_system_variables);
+ key_cache->in_init= 0;
}
- return 0;
+ /*
+ We don't delete the key cache as some running threads my still be
+ in the key cache code with a pointer to the deleted (empty) key cache
+ */
+ goto end;
}
key_cache->buff_size= (ulonglong) getopt_ull_limit_value(tmp, option_limits);
+ /* If key cache didn't existed initialize it, else resize it */
+ key_cache->in_init= 1;
+ pthread_mutex_unlock(&LOCK_global_system_variables);
+
if (!key_cache->cache)
- return (bool)(ha_key_cache(key_cache));
+ error= (bool) (ha_init_key_cache("", key_cache));
else
- return (bool)(ha_resize_key_cache(key_cache));
-}
+ error= (bool)(ha_resize_key_cache(key_cache));
-bool sys_var_key_cache_block_size::update(THD *thd, set_var *var)
-{
- ulong tmp= var->value->val_int();
- LEX_STRING *base_name= &var->base;
- if (!base_name->length)
- base_name= &default_key_cache_base;
- KEY_CACHE_VAR *key_cache= get_key_cache(base_name);
-
- if (!key_cache && !(key_cache= create_key_cache(base_name->str,
- base_name->length)))
- return 1;
-
- key_cache->block_size= (ulong) getopt_ull_limit_value(tmp, option_limits);
+ pthread_mutex_lock(&LOCK_global_system_variables);
+ key_cache->in_init= 0;
- if (key_cache->cache)
- /* Do not build a new key cache here */
- return (bool) (ha_resize_key_cache(key_cache));
- return 0;
+end:
+ pthread_mutex_unlock(&LOCK_global_system_variables);
+ return error;
}
-bool sys_var_key_cache_division_limit::update(THD *thd, set_var *var)
+
+bool sys_var_key_cache_long::update(THD *thd, set_var *var)
{
ulong tmp= var->value->val_int();
LEX_STRING *base_name= &var->base;
+ bool error= 0;
+
if (!base_name->length)
base_name= &default_key_cache_base;
+
+ pthread_mutex_lock(&LOCK_global_system_variables);
KEY_CACHE_VAR *key_cache= get_key_cache(base_name);
if (!key_cache && !(key_cache= create_key_cache(base_name->str,
base_name->length)))
- return 1;
+ {
+ error= 1;
+ goto end;
+ }
- key_cache->division_limit=
+ /*
+ Abort if some other thread is changing the key cache
+ TODO: This should be changed so that we wait until the previous
+ assignment is done and then do the new assign
+ */
+ if (key_cache->in_init)
+ goto end;
+
+ *((ulong*) (((char*) key_cache) + offset))=
(ulong) getopt_ull_limit_value(tmp, option_limits);
- if (key_cache->cache)
- /* Do not build a new key cache here */
- return (bool) (ha_change_key_cache_param(key_cache));
- return 0;
-}
+ /*
+ Don't create a new key cache if it didn't exist
+ (key_caches are created only when the user sets block_size)
+ */
+ key_cache->in_init= 1;
-bool sys_var_key_cache_age_threshold::update(THD *thd, set_var *var)
-{
- ulong tmp= var->value->val_int();
- LEX_STRING *base_name= &var->base;
- if (!base_name->length)
- base_name= &default_key_cache_base;
- KEY_CACHE_VAR *key_cache= get_key_cache(base_name);
-
- if (!key_cache && !(key_cache= create_key_cache(base_name->str,
- base_name->length)))
- return 1;
-
- key_cache->division_limit=
- (ulong) getopt_ull_limit_value(tmp, option_limits);
+ pthread_mutex_unlock(&LOCK_global_system_variables);
- if (key_cache->cache)
- /* Do not build a new key cache here */
- return (bool) (ha_change_key_cache_param(key_cache));
- return 0;
+ error= (bool) (ha_resize_key_cache(key_cache));
+
+ pthread_mutex_lock(&LOCK_global_system_variables);
+ key_cache->in_init= 0;
+
+end:
+ pthread_mutex_unlock(&LOCK_global_system_variables);
+ return error;
}
@@ -2506,13 +2527,14 @@ gptr find_named(I_List<NAMED_LIST> *list, const char *name, uint length,
}
-void delete_elements(I_List<NAMED_LIST> *list, void (*free_element)(gptr))
+void delete_elements(I_List<NAMED_LIST> *list,
+ void (*free_element)(const char *name, gptr))
{
NAMED_LIST *element;
DBUG_ENTER("delete_elements");
while ((element= list->get()))
{
- (*free_element)(element->data);
+ (*free_element)(element->name, element->data);
delete element;
}
DBUG_VOID_RETURN;
@@ -2524,60 +2546,65 @@ void delete_elements(I_List<NAMED_LIST> *list, void (*free_element)(gptr))
static KEY_CACHE_VAR *create_key_cache(const char *name, uint length)
{
KEY_CACHE_VAR *key_cache;
- DBUG_PRINT("info",("Creating key cache: %.*s length: %d", length, name,
- length));
- if (length != default_key_cache_base.length ||
- memcmp(name, default_key_cache_base.str, length))
- {
- if ((key_cache= (KEY_CACHE_VAR*) my_malloc(sizeof(KEY_CACHE_VAR),
- MYF(MY_ZEROFILL | MY_WME))))
- {
- if (!new NAMED_LIST(&key_caches, name, length, (gptr) key_cache))
- {
- my_free((char*) key_cache, MYF(0));
- key_cache= 0;
- }
- }
- }
- else
+ DBUG_ENTER("create_key_cache");
+ DBUG_PRINT("enter",("name: %.*s", length, name));
+
+ if ((key_cache= (KEY_CACHE_VAR*) my_malloc(sizeof(KEY_CACHE_VAR),
+ MYF(MY_ZEROFILL | MY_WME))))
{
- key_cache= &dflt_key_cache_var;
if (!new NAMED_LIST(&key_caches, name, length, (gptr) key_cache))
+ {
+ my_free((char*) key_cache, MYF(0));
key_cache= 0;
+ }
+ else
+ {
+ /*
+ Set default values for a key cache
+ The values in dflt_key_cache_var is set by my_getopt() at startup
+
+ We don't set 'buff_size' as this is used to enable the key cache
+ */
+ key_cache->block_size= dflt_key_cache_var.block_size;
+ key_cache->division_limit= dflt_key_cache_var.division_limit;
+ key_cache->age_threshold= dflt_key_cache_var.age_threshold;
+ }
}
-
- return key_cache;
+ DBUG_RETURN(key_cache);
}
KEY_CACHE_VAR *get_or_create_key_cache(const char *name, uint length)
{
LEX_STRING key_cache_name;
+ KEY_CACHE_VAR *key_cache;
+
key_cache_name.str= (char *) name;
key_cache_name.length= length;
- KEY_CACHE_VAR *key_cache= get_key_cache(&key_cache_name);
- if (!key_cache)
+ pthread_mutex_lock(&LOCK_global_system_variables);
+ if (!(key_cache= get_key_cache(&key_cache_name)))
key_cache= create_key_cache(name, length);
+ pthread_mutex_unlock(&LOCK_global_system_variables);
return key_cache;
}
-void free_key_cache(gptr key_cache)
+void free_key_cache(const char *name, KEY_CACHE_VAR *key_cache)
{
- if (key_cache != (gptr) &dflt_key_cache_var)
- my_free(key_cache, MYF(0));
+ ha_end_key_cache(key_cache);
+ my_free((char*) key_cache, MYF(0));
}
-bool process_key_caches(int (* func) (KEY_CACHE_VAR *))
-{
+bool process_key_caches(int (* func) (const char *name, KEY_CACHE_VAR *))
+{
I_List_iterator<NAMED_LIST> it(key_caches);
NAMED_LIST *element;
+
while ((element= it++))
{
KEY_CACHE_VAR *key_cache= (KEY_CACHE_VAR *) element->data;
- if (key_cache != &dflt_key_cache_var)
- func(key_cache);
+ func(element->name, key_cache);
}
return 0;
}
diff --git a/sql/set_var.h b/sql/set_var.h
index c799eec750a..a4c3b546fe0 100644
--- a/sql/set_var.h
+++ b/sql/set_var.h
@@ -30,11 +30,6 @@ class set_var;
typedef struct system_variables SV;
extern TYPELIB bool_typelib, delay_key_write_typelib, sql_mode_typelib;
-extern ulonglong dflt_key_buff_size;
-extern uint dflt_key_cache_block_size;
-extern uint dflt_key_cache_division_limit;
-extern uint dflt_key_cache_age_threshold;
-
enum enum_var_type
{
OPT_DEFAULT, OPT_SESSION, OPT_GLOBAL
@@ -546,73 +541,40 @@ public:
byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base);
};
+
class sys_var_key_cache_param :public sys_var
{
protected:
- uint offset;
+ size_t offset;
public:
- sys_var_key_cache_param(const char *name_arg)
- :sys_var(name_arg)
- {
- offset= 0;
- }
+ sys_var_key_cache_param(const char *name_arg, size_t offset_arg)
+ :sys_var(name_arg), offset(offset_arg)
+ {}
byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base);
+ bool check_default(enum_var_type type) { return 1; }
+ bool is_struct() { return 1; }
};
+
class sys_var_key_buffer_size :public sys_var_key_cache_param
{
public:
sys_var_key_buffer_size(const char *name_arg)
- :sys_var_key_cache_param(name_arg)
- {
- offset= offsetof(KEY_CACHE_VAR, buff_size);
- }
+ :sys_var_key_cache_param(name_arg, offsetof(KEY_CACHE_VAR, buff_size))
+ {}
bool update(THD *thd, set_var *var);
SHOW_TYPE type() { return SHOW_LONGLONG; }
- bool check_default(enum_var_type type) { return 1; }
- bool is_struct() { return 1; }
-};
-
-class sys_var_key_cache_block_size :public sys_var_key_cache_param
-{
-public:
- sys_var_key_cache_block_size(const char *name_arg)
- :sys_var_key_cache_param(name_arg)
- {
- offset= offsetof(KEY_CACHE_VAR, block_size);
- }
- bool update(THD *thd, set_var *var);
- SHOW_TYPE type() { return SHOW_LONG; }
- bool check_default(enum_var_type type) { return 1; }
- bool is_struct() { return 1; }
};
-class sys_var_key_cache_division_limit :public sys_var_key_cache_param
-{
-public:
- sys_var_key_cache_division_limit(const char *name_arg)
- :sys_var_key_cache_param(name_arg)
- {
- offset= offsetof(KEY_CACHE_VAR, division_limit);
- }
- bool update(THD *thd, set_var *var);
- SHOW_TYPE type() { return SHOW_LONG; }
- bool check_default(enum_var_type type) { return 1; }
- bool is_struct() { return 1; }
-};
-class sys_var_key_cache_age_threshold :public sys_var_key_cache_param
+class sys_var_key_cache_long :public sys_var_key_cache_param
{
public:
- sys_var_key_cache_age_threshold(const char *name_arg)
- :sys_var_key_cache_param(name_arg)
- {
- offset= offsetof(KEY_CACHE_VAR, age_threshold);
- }
+ sys_var_key_cache_long(const char *name_arg, size_t offset_arg)
+ :sys_var_key_cache_param(name_arg, offset_arg)
+ {}
bool update(THD *thd, set_var *var);
SHOW_TYPE type() { return SHOW_LONG; }
- bool check_default(enum_var_type type) { return 1; }
- bool is_struct() { return 1; }
};
@@ -781,7 +743,7 @@ public:
uint name_length_arg, gptr data_arg)
:name_length(name_length_arg), data(data_arg)
{
- name= my_memdup((byte*) name_arg, name_length, MYF(MY_WME));
+ name= my_strdup_with_length((byte*) name_arg, name_length, MYF(MY_WME));
links->push_back(this);
}
inline bool cmp(const char *name_cmp, uint length)
@@ -792,11 +754,16 @@ public:
{
my_free((char*) name, MYF(0));
}
+ friend bool process_key_caches(int (* func) (const char *name,
+ KEY_CACHE_VAR *));
+ friend void delete_elements(I_List<NAMED_LIST> *list,
+ void (*free_element)(const char*, gptr));
};
/* updated in sql_acl.cc */
extern sys_var_thd_bool sys_old_passwords;
+extern LEX_STRING default_key_cache_base;
/* For sql_yacc */
struct sys_var_with_base
@@ -819,9 +786,8 @@ extern sys_var_str sys_charset_system;
CHARSET_INFO *get_old_charset_by_name(const char *old_name);
gptr find_named(I_List<NAMED_LIST> *list, const char *name, uint length,
NAMED_LIST **found);
-void delete_elements(I_List<NAMED_LIST> *list, void (*free_element)(gptr));
/* key_cache functions */
+KEY_CACHE_VAR *get_key_cache(LEX_STRING *cache_name);
KEY_CACHE_VAR *get_or_create_key_cache(const char *name, uint length);
-void free_key_cache(gptr key_cache);
-bool process_key_caches(int (* func) (KEY_CACHE_VAR *));
+void free_key_cache(const char *name, KEY_CACHE_VAR *key_cache);
diff --git a/sql/share/czech/errmsg.txt b/sql/share/czech/errmsg.txt
index befba24be1c..dffaf98197f 100644
--- a/sql/share/czech/errmsg.txt
+++ b/sql/share/czech/errmsg.txt
@@ -298,3 +298,4 @@ character-set=latin2
"Incorrect catalog name '%-.100s'",
"Query cache failed to set size %lu, new query cache size is %lu",
"Column '%-.64s' cannot be part of FULLTEXT index",
+"Unknown key cache '%-.100s'",
diff --git a/sql/share/danish/errmsg.txt b/sql/share/danish/errmsg.txt
index 0a980439816..ebf7a2c3f84 100644
--- a/sql/share/danish/errmsg.txt
+++ b/sql/share/danish/errmsg.txt
@@ -292,3 +292,4 @@ character-set=latin1
"Incorrect catalog name '%-.100s'",
"Query cache failed to set size %lu, new query cache size is %lu",
"Column '%-.64s' cannot be part of FULLTEXT index",
+"Unknown key cache '%-.100s'",
diff --git a/sql/share/dutch/errmsg.txt b/sql/share/dutch/errmsg.txt
index 8a415aeaec1..7d94c907ae3 100644
--- a/sql/share/dutch/errmsg.txt
+++ b/sql/share/dutch/errmsg.txt
@@ -300,3 +300,4 @@ character-set=latin1
"Incorrect catalog name '%-.100s'",
"Query cache failed to set size %lu, new query cache size is %lu",
"Column '%-.64s' cannot be part of FULLTEXT index",
+"Unknown key cache '%-.100s'",
diff --git a/sql/share/english/errmsg.txt b/sql/share/english/errmsg.txt
index c281fb2e781..891e23ad917 100644
--- a/sql/share/english/errmsg.txt
+++ b/sql/share/english/errmsg.txt
@@ -289,3 +289,4 @@ character-set=latin1
"Incorrect catalog name '%-.100s'",
"Query cache failed to set size %lu, new query cache size is %lu",
"Column '%-.64s' cannot be part of FULLTEXT index",
+"Unknown key cache '%-.100s'",
diff --git a/sql/share/estonian/errmsg.txt b/sql/share/estonian/errmsg.txt
index 75dca762604..f6b416f49fb 100644
--- a/sql/share/estonian/errmsg.txt
+++ b/sql/share/estonian/errmsg.txt
@@ -294,3 +294,4 @@ character-set=latin7
"Incorrect catalog name '%-.100s'",
"Query cache failed to set size %lu, new query cache size is %lu",
"Column '%-.64s' cannot be part of FULLTEXT index",
+"Unknown key cache '%-.100s'",
diff --git a/sql/share/french/errmsg.txt b/sql/share/french/errmsg.txt
index fa374188768..c6a47091d54 100644
--- a/sql/share/french/errmsg.txt
+++ b/sql/share/french/errmsg.txt
@@ -289,3 +289,4 @@ character-set=latin1
"Incorrect catalog name '%-.100s'",
"Query cache failed to set size %lu, new query cache size is %lu",
"Column '%-.64s' cannot be part of FULLTEXT index",
+"Unknown key cache '%-.100s'",
diff --git a/sql/share/german/errmsg.txt b/sql/share/german/errmsg.txt
index 2e69f783a4c..fe49d1c1e66 100644
--- a/sql/share/german/errmsg.txt
+++ b/sql/share/german/errmsg.txt
@@ -301,3 +301,4 @@ character-set=latin1
"Incorrect catalog name '%-.100s'",
"Query cache failed to set size %lu, new query cache size is %lu",
"Column '%-.64s' cannot be part of FULLTEXT index",
+"Unknown key cache '%-.100s'",
diff --git a/sql/share/greek/errmsg.txt b/sql/share/greek/errmsg.txt
index eb1d64266b0..3f6f2e5f5b2 100644
--- a/sql/share/greek/errmsg.txt
+++ b/sql/share/greek/errmsg.txt
@@ -289,3 +289,4 @@ character-set=greek
"Incorrect catalog name '%-.100s'",
"Query cache failed to set size %lu, new query cache size is %lu",
"Column '%-.64s' cannot be part of FULLTEXT index",
+"Unknown key cache '%-.100s'",
diff --git a/sql/share/hungarian/errmsg.txt b/sql/share/hungarian/errmsg.txt
index 3be28918bff..7776655d0b9 100644
--- a/sql/share/hungarian/errmsg.txt
+++ b/sql/share/hungarian/errmsg.txt
@@ -291,3 +291,4 @@ character-set=latin2
"Incorrect catalog name '%-.100s'",
"Query cache failed to set size %lu, new query cache size is %lu",
"Column '%-.64s' cannot be part of FULLTEXT index",
+"Unknown key cache '%-.100s'",
diff --git a/sql/share/italian/errmsg.txt b/sql/share/italian/errmsg.txt
index 535a20b04e8..dc4392a0ed8 100644
--- a/sql/share/italian/errmsg.txt
+++ b/sql/share/italian/errmsg.txt
@@ -289,3 +289,4 @@ character-set=latin1
"Incorrect catalog name '%-.100s'",
"Query cache failed to set size %lu, new query cache size is %lu",
"Column '%-.64s' cannot be part of FULLTEXT index",
+"Unknown key cache '%-.100s'",
diff --git a/sql/share/japanese/errmsg.txt b/sql/share/japanese/errmsg.txt
index 1c7e6a9e9a4..101c6a22430 100644
--- a/sql/share/japanese/errmsg.txt
+++ b/sql/share/japanese/errmsg.txt
@@ -291,3 +291,4 @@ character-set=ujis
"Incorrect catalog name '%-.100s'",
"Query cache failed to set size %lu, new query cache size is %lu",
"Column '%-.64s' cannot be part of FULLTEXT index",
+"Unknown key cache '%-.100s'",
diff --git a/sql/share/korean/errmsg.txt b/sql/share/korean/errmsg.txt
index 8d3ab9dad02..0337ad97a21 100644
--- a/sql/share/korean/errmsg.txt
+++ b/sql/share/korean/errmsg.txt
@@ -289,3 +289,4 @@ character-set=euckr
"Incorrect catalog name '%-.100s'",
"Query cache failed to set size %lu, new query cache size is %lu",
"Column '%-.64s' cannot be part of FULLTEXT index",
+"Unknown key cache '%-.100s'",
diff --git a/sql/share/norwegian-ny/errmsg.txt b/sql/share/norwegian-ny/errmsg.txt
index ae6a76a8cba..549961aef23 100644
--- a/sql/share/norwegian-ny/errmsg.txt
+++ b/sql/share/norwegian-ny/errmsg.txt
@@ -291,3 +291,4 @@ character-set=latin1
"Incorrect catalog name '%-.100s'",
"Query cache failed to set size %lu, new query cache size is %lu",
"Column '%-.64s' cannot be part of FULLTEXT index",
+"Unknown key cache '%-.100s'",
diff --git a/sql/share/norwegian/errmsg.txt b/sql/share/norwegian/errmsg.txt
index 4fbb13599c2..f1ff1a15415 100644
--- a/sql/share/norwegian/errmsg.txt
+++ b/sql/share/norwegian/errmsg.txt
@@ -291,3 +291,4 @@ character-set=latin1
"Incorrect catalog name '%-.100s'",
"Query cache failed to set size %lu, new query cache size is %lu",
"Column '%-.64s' cannot be part of FULLTEXT index",
+"Unknown key cache '%-.100s'",
diff --git a/sql/share/polish/errmsg.txt b/sql/share/polish/errmsg.txt
index a7530d89bbe..f3c9c929c28 100644
--- a/sql/share/polish/errmsg.txt
+++ b/sql/share/polish/errmsg.txt
@@ -293,3 +293,4 @@ character-set=latin2
"Incorrect catalog name '%-.100s'",
"Query cache failed to set size %lu, new query cache size is %lu",
"Column '%-.64s' cannot be part of FULLTEXT index",
+"Unknown key cache '%-.100s'",
diff --git a/sql/share/portuguese/errmsg.txt b/sql/share/portuguese/errmsg.txt
index d39429e08b8..3bbf1d5468f 100644
--- a/sql/share/portuguese/errmsg.txt
+++ b/sql/share/portuguese/errmsg.txt
@@ -290,3 +290,4 @@ character-set=latin1
"Incorrect catalog name '%-.100s'",
"Query cache failed to set size %lu, new query cache size is %lu",
"Column '%-.64s' cannot be part of FULLTEXT index",
+"Unknown key cache '%-.100s'",
diff --git a/sql/share/romanian/errmsg.txt b/sql/share/romanian/errmsg.txt
index 87420563db6..1222240621c 100644
--- a/sql/share/romanian/errmsg.txt
+++ b/sql/share/romanian/errmsg.txt
@@ -293,3 +293,4 @@ character-set=latin2
"Incorrect catalog name '%-.100s'",
"Query cache failed to set size %lu, new query cache size is %lu",
"Column '%-.64s' cannot be part of FULLTEXT index",
+"Unknown key cache '%-.100s'",
diff --git a/sql/share/russian/errmsg.txt b/sql/share/russian/errmsg.txt
index 1d452f54c46..1df627ebe7c 100644
--- a/sql/share/russian/errmsg.txt
+++ b/sql/share/russian/errmsg.txt
@@ -291,3 +291,4 @@ character-set=koi8r
"Incorrect catalog name '%-.100s'",
"ëÅÛ ÚÁÐÒÏÓÏ× ÎÅ ÍÏÖÅÔ ÕÓÔÁÎÏ×ÉÔØ ÒÁÚÍÅÒ %lu, ÎÏ×ÙÊ ÒÁÚÍÅÒ ËÅÛÁ ÚÐÒÏÓÏ× - %lu",
"Column '%-.64s' cannot be part of FULLTEXT index",
+"Unknown key cache '%-.100s'",
diff --git a/sql/share/serbian/errmsg.txt b/sql/share/serbian/errmsg.txt
index 8386d1439a6..ebac72233b3 100644
--- a/sql/share/serbian/errmsg.txt
+++ b/sql/share/serbian/errmsg.txt
@@ -284,3 +284,4 @@ character-set=cp1250
"Incorrect catalog name '%-.100s'",
"Query cache failed to set size %lu, new query cache size is %lu",
"Column '%-.64s' cannot be part of FULLTEXT index",
+"Unknown key cache '%-.100s'",
diff --git a/sql/share/slovak/errmsg.txt b/sql/share/slovak/errmsg.txt
index 0fda1252f6b..552d71805e1 100644
--- a/sql/share/slovak/errmsg.txt
+++ b/sql/share/slovak/errmsg.txt
@@ -297,3 +297,4 @@ character-set=latin2
"Incorrect catalog name '%-.100s'",
"Query cache failed to set size %lu, new query cache size is %lu",
"Column '%-.64s' cannot be part of FULLTEXT index",
+"Unknown key cache '%-.100s'",
diff --git a/sql/share/spanish/errmsg.txt b/sql/share/spanish/errmsg.txt
index 4d8fbbb208e..a4f590d45e8 100644
--- a/sql/share/spanish/errmsg.txt
+++ b/sql/share/spanish/errmsg.txt
@@ -291,3 +291,4 @@ character-set=latin1
"Incorrect catalog name '%-.100s'",
"Query cache failed to set size %lu, new query cache size is %lu",
"Column '%-.64s' cannot be part of FULLTEXT index",
+"Unknown key cache '%-.100s'",
diff --git a/sql/share/swedish/errmsg.txt b/sql/share/swedish/errmsg.txt
index 0f488750be5..15a1562e4a0 100644
--- a/sql/share/swedish/errmsg.txt
+++ b/sql/share/swedish/errmsg.txt
@@ -289,3 +289,4 @@ character-set=latin1
"Incorrect catalog name '%-.100s'",
"Storleken av "Query cache" kunde inte sättas till %lu, ny storlek är %lu",
"Kolumn '%-.64s' kan inte vara del av ett FULLTEXT index",
+"Unknown key cache '%-.100s'",
diff --git a/sql/share/ukrainian/errmsg.txt b/sql/share/ukrainian/errmsg.txt
index 5a8c6090e80..71fddf604c9 100644
--- a/sql/share/ukrainian/errmsg.txt
+++ b/sql/share/ukrainian/errmsg.txt
@@ -294,3 +294,4 @@ character-set=koi8u
"Incorrect catalog name '%-.100s'",
"ëÅÛ ÚÁÐÉÔ¦× ÎÅÓÐÒÏÍÏÖÅÎ ×ÓÔÁÎÏ×ÉÔÉ ÒÏÚÍ¦Ò %lu, ÎÏ×ÉÊ ÒÏÚÍ¦Ò ËÅÛÁ ÚÁÐÉÔ¦× - %lu",
"Column '%-.64s' cannot be part of FULLTEXT index",
+"Unknown key cache '%-.100s'",
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 3976ebd81f4..9fe61ae19e1 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -35,6 +35,7 @@ HASH assign_cache;
static int open_unireg_entry(THD *thd,TABLE *entry,const char *db,
const char *name, const char *alias);
static void free_cache_entry(TABLE *entry);
+static void free_assign_entry(KEY_CACHE_ASMT *key_cache_asmt);
static void mysql_rm_tmp_tables(void);
@@ -142,7 +143,8 @@ OPEN_TABLE_LIST *list_open_tables(THD *thd, const char *wild)
OPEN_TABLE_LIST *table;
TABLE *entry=(TABLE*) hash_element(&open_cache,idx);
- if ((!entry->real_name))
+ DBUG_ASSERT(entry->real_name);
+ if ((!entry->real_name)) // To be removed
continue; // Shouldn't happen
if (wild)
{
@@ -772,8 +774,6 @@ TABLE *open_table(THD *thd,const char *db,const char *table_name,
reg1 TABLE *table;
char key[MAX_DBKEY_LENGTH];
uint key_length;
- KEY_CACHE_ASMT *key_cache_asmt;
- KEY_CACHE_VAR *key_cache;
DBUG_ENTER("open_table");
/* find a unused table in the open table cache */
@@ -816,76 +816,6 @@ TABLE *open_table(THD *thd,const char *db,const char *table_name,
DBUG_RETURN(0);
}
- VOID(pthread_mutex_lock(&LOCK_assign));
- key_cache_asmt= (KEY_CACHE_ASMT*) hash_search(&assign_cache,
- (byte*) key, key_length) ;
- if (thd->open_options & HA_OPEN_TO_ASSIGN)
- {
- /* When executing a CACHE INDEX command*/
- if (key_cache_asmt)
- {
- if (key_cache_asmt->requests++)
- {
- /* Another thread are assigning this table to some key cache*/
-
- /* Put the assignment request into the queue of such requests */
- struct st_my_thread_var *last;
- struct st_my_thread_var *thread= thd->mysys_var;
- if (! (last= key_cache_asmt->queue))
- thread->next= thread;
- else
- {
- thread->next= last->next;
- last->next= thread;
- }
- key_cache_asmt->queue= thread;
-
- /* Wait until the request can be processed */
- do
- {
- VOID(pthread_cond_wait(&thread->suspend, &LOCK_assign));
- }
- while (thread->next);
- }
- }
- else
- {
- /*
- The table has not been explicitly assigned to any key cache yet;
- by default it's assigned to the default key cache;
- */
-
- if (!(key_cache_asmt=
- (KEY_CACHE_ASMT *) my_malloc(sizeof(*key_cache_asmt),
- MYF(MY_WME | MY_ZEROFILL))) ||
- !(key_cache_asmt->db_name= my_strdup(db, MYF(MY_WME))) ||
- !(key_cache_asmt->table_name= my_strdup(table_name, MYF(MY_WME))) ||
- !(key_cache_asmt->table_key= my_memdup((const byte *) key,
- key_length, MYF(MY_WME))))
- {
- VOID(pthread_mutex_unlock(&LOCK_assign));
-
- if (key_cache_asmt)
- {
- if (key_cache_asmt->db_name)
- my_free((gptr) key_cache_asmt->db_name, MYF(0));
- if (key_cache_asmt->table_name)
- my_free((gptr) key_cache_asmt->table_name, MYF(0));
- my_free((gptr) key_cache_asmt, MYF(0));
- }
- DBUG_RETURN(NULL);
- }
- key_cache_asmt->key_length= key_length;
- key_cache_asmt->key_cache= &dflt_key_cache_var;
- VOID(my_hash_insert(&assign_cache, (byte *) key_cache_asmt));
- key_cache_asmt->requests++;
- }
- key_cache_asmt->to_reassign= 0;
- }
-
- key_cache= key_cache_asmt ? key_cache_asmt->key_cache : &dflt_key_cache_var;
- VOID(pthread_mutex_unlock(&LOCK_assign));
-
VOID(pthread_mutex_lock(&LOCK_open));
if (!thd->open_tables)
@@ -929,8 +859,6 @@ TABLE *open_table(THD *thd,const char *db,const char *table_name,
table->prev->next=table->next; /* Remove from unused list */
table->next->prev=table->prev;
- table->key_cache= key_cache;
- table->key_cache_asmt= key_cache_asmt;
}
else
{
@@ -944,8 +872,6 @@ TABLE *open_table(THD *thd,const char *db,const char *table_name,
VOID(pthread_mutex_unlock(&LOCK_open));
DBUG_RETURN(NULL);
}
- table->key_cache= key_cache;
- table->key_cache_asmt= key_cache_asmt;
if (open_unireg_entry(thd, table,db,table_name,alias) ||
!(table->table_cache_key=memdup_root(&table->mem_root,(char*) key,
key_length)))
@@ -963,8 +889,7 @@ TABLE *open_table(THD *thd,const char *db,const char *table_name,
}
table->in_use=thd;
- check_unused();
-
+ check_unused(); // Debugging call
VOID(pthread_mutex_unlock(&LOCK_open));
if (refresh)
@@ -1071,8 +996,8 @@ bool reopen_table(TABLE *table,bool locked)
tmp.grant= table->grant;
/* Replace table in open list */
- tmp.next=table->next;
- tmp.prev=table->prev;
+ tmp.next= table->next;
+ tmp.prev= table->prev;
if (table->file)
VOID(closefrm(table)); // close file, free everything
@@ -1740,54 +1665,6 @@ bool rm_temporary_table(enum db_type base, char *path)
DBUG_RETURN(error);
}
-static void free_assign_entry(KEY_CACHE_ASMT *key_cache_asmt)
-{
- DBUG_ENTER("free_assign_entry");
- my_free((gptr) key_cache_asmt->table_key, MYF(0));
- my_free((gptr) key_cache_asmt, MYF(0));
- DBUG_VOID_RETURN;
-}
-
-static byte *assign_cache_key(const byte *record,uint *length,
- my_bool not_used __attribute__((unused)))
-{
- KEY_CACHE_ASMT *entry=(KEY_CACHE_ASMT *) record;
- *length=entry->key_length;
- return (byte*) entry->table_key;
-}
-
-void assign_cache_init(void)
-{
- VOID(hash_init(&assign_cache, &my_charset_bin,
- table_cache_size+16, 0, 0, assign_cache_key,
- (hash_free_key) free_assign_entry,0));
-}
-
-void assign_cache_free(void)
-{
- DBUG_ENTER("assign_cache_free");
- hash_free(&assign_cache);
- DBUG_VOID_RETURN;
-}
-
-void reassign_key_cache(KEY_CACHE_ASMT *key_cache_asmt,
- KEY_CACHE_VAR *new_key_cache)
-{
- if (key_cache_asmt->prev)
- {
- /* Unlink key_cache_asmt from the assignment list for the old key cache */
- if ((*key_cache_asmt->prev= key_cache_asmt->next))
- key_cache_asmt->next->prev= key_cache_asmt->prev;
- }
- /* Link key_cache_asmt into the assignment list for the new key cache */
- key_cache_asmt->prev= &new_key_cache->assign_list;
- if ((key_cache_asmt->next= new_key_cache->assign_list))
- key_cache_asmt->next->prev= &key_cache_asmt->next;
- new_key_cache->assign_list= key_cache_asmt;
-
- key_cache_asmt->key_cache= new_key_cache;
-}
-
/*****************************************************************************
** find field in list or tables. if field is unqualifed and unique,
@@ -2215,7 +2092,21 @@ bool setup_tables(TABLE_LIST *tables)
}
-void get_key_map_from_key_list(key_map *map, TABLE *table,
+/*
+ Create a key_map from a list of index names
+
+ SYNOPSIS
+ get_key_map_from_key_list()
+ map key_map to fill in
+ table Table
+ index_list List of index names
+
+ RETURN
+ 0 ok; In this case *map will includes the choosed index
+ 1 error
+*/
+
+bool get_key_map_from_key_list(key_map *map, TABLE *table,
List<String> *index_list)
{
List_iterator_fast<String> it(*index_list);
@@ -2231,13 +2122,14 @@ void get_key_map_from_key_list(key_map *map, TABLE *table,
my_error(ER_KEY_COLUMN_DOES_NOT_EXITS, MYF(0), name->c_ptr(),
table->real_name);
map->set_all();
- return;
+ return 1;
}
map->set_bit(pos-1);
}
- return;
+ return 0;
}
+
/****************************************************************************
This just drops in all fields instead of current '*' field
Returns pointer to last inserted field if ok
@@ -2488,7 +2380,7 @@ int mysql_create_index(THD *thd, TABLE_LIST *table_list, List<Key> &keys)
DBUG_ENTER("mysql_create_index");
bzero((char*) &create_info,sizeof(create_info));
create_info.db_type=DB_TYPE_DEFAULT;
- create_info.table_charset= thd->variables.collation_database;
+ create_info.default_table_charset= thd->variables.collation_database;
DBUG_RETURN(mysql_alter_table(thd,table_list->db,table_list->real_name,
&create_info, table_list,
fields, keys, drop, alter, 0, (ORDER*)0, FALSE,
@@ -2505,7 +2397,7 @@ int mysql_drop_index(THD *thd, TABLE_LIST *table_list, List<Alter_drop> &drop)
DBUG_ENTER("mysql_drop_index");
bzero((char*) &create_info,sizeof(create_info));
create_info.db_type=DB_TYPE_DEFAULT;
- create_info.table_charset= thd->variables.collation_database;
+ create_info.default_table_charset= thd->variables.collation_database;
DBUG_RETURN(mysql_alter_table(thd,table_list->db,table_list->real_name,
&create_info, table_list,
fields, keys, drop, alter, 0, (ORDER*)0, FALSE,
diff --git a/sql/sql_db.cc b/sql/sql_db.cc
index 09d32dfa5ee..d4e3fe753d3 100644
--- a/sql/sql_db.cc
+++ b/sql/sql_db.cc
@@ -60,10 +60,12 @@ static bool write_db_opt(THD *thd, const char *path, HA_CREATE_INFO *create)
if ((file=my_create(path, CREATE_MODE,O_RDWR | O_TRUNC,MYF(MY_WME))) >= 0)
{
ulong length;
- CHARSET_INFO *cs= (create && create->table_charset) ?
- create->table_charset :
+ CHARSET_INFO *cs= (create && create->default_table_charset) ?
+ create->default_table_charset :
thd->variables.collation_database;
- length= my_sprintf(buf,(buf, "default-character-set=%s\ndefault-collation=%s\n", cs->csname,cs->name));
+ length= my_sprintf(buf,(buf,
+ "default-character-set=%s\ndefault-collation=%s\n",
+ cs->csname,cs->name));
/* Error is written by my_write */
if (!my_write(file,(byte*) buf, length, MYF(MY_NABP+MY_WME)))
@@ -99,7 +101,7 @@ static bool load_db_opt(THD *thd, const char *path, HA_CREATE_INFO *create)
uint nbytes;
bzero((char*) create,sizeof(*create));
- create->table_charset= global_system_variables.collation_database;
+ create->default_table_charset= global_system_variables.collation_database;
if ((file=my_open(path, O_RDONLY | O_SHARE, MYF(0))) >= 0)
{
IO_CACHE cache;
@@ -116,16 +118,17 @@ static bool load_db_opt(THD *thd, const char *path, HA_CREATE_INFO *create)
{
if (!strncmp(buf,"default-character-set", (pos-buf)))
{
- if (!(create->table_charset=get_charset_by_csname(pos+1,
- MY_CS_PRIMARY,
- MYF(0))))
+ if (!(create->default_table_charset= get_charset_by_csname(pos+1,
+ MY_CS_PRIMARY,
+ MYF(0))))
{
sql_print_error(ER(ER_UNKNOWN_CHARACTER_SET),pos+1);
}
}
else if (!strncmp(buf,"default-collation", (pos-buf)))
{
- if (!(create->table_charset=get_charset_by_name(pos+1, MYF(0))))
+ if (!(create->default_table_charset= get_charset_by_name(pos+1,
+ MYF(0))))
{
sql_print_error(ER(ER_UNKNOWN_COLLATION),pos+1);
}
@@ -286,8 +289,8 @@ int mysql_alter_db(THD *thd, const char *db, HA_CREATE_INFO *create_info)
*/
if (thd->db && !strcmp(thd->db,db))
{
- thd->db_charset= (create_info && create_info->table_charset) ?
- create_info->table_charset :
+ thd->db_charset= (create_info && create_info->default_table_charset) ?
+ create_info->default_table_charset :
global_system_variables.collation_database;
thd->variables.collation_database= thd->db_charset;
}
@@ -653,8 +656,8 @@ bool mysql_change_db(THD *thd, const char *name)
#endif
strmov(path+unpack_dirname(path,path), MY_DB_OPT_FILE);
load_db_opt(thd, path, &create);
- thd->db_charset= create.table_charset ?
- create.table_charset :
+ thd->db_charset= create.default_table_charset ?
+ create.default_table_charset :
global_system_variables.collation_database;
thd->variables.collation_database= thd->db_charset;
DBUG_RETURN(0);
@@ -731,12 +734,13 @@ int mysqld_show_create_db(THD *thd, char *dbname,
to= strxmov(to,"/*!32312 IF NOT EXISTS*/ ", NullS);
to=strxmov(to,"`",dbname,"`", NullS);
- if (create.table_charset)
+ if (create.default_table_charset)
{
- int cl= (create.table_charset->state & MY_CS_PRIMARY) ? 0 : 1;
+ int cl= (create.default_table_charset->state & MY_CS_PRIMARY) ? 0 : 1;
to= strxmov(to," /*!40100"
- " DEFAULT CHARACTER SET ",create.table_charset->csname,
- cl ? " COLLATE " : "", cl ? create.table_charset->name : "",
+ " DEFAULT CHARACTER SET ",create.default_table_charset->csname,
+ cl ? " COLLATE " : "",
+ cl ? create.default_table_charset->name : "",
" */",NullS);
}
protocol->store(path, (uint) (to-path), system_charset_info);
diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc
index 2985f7e04a0..eccf0e6dbe0 100644
--- a/sql/sql_delete.cc
+++ b/sql/sql_delete.cc
@@ -560,8 +560,8 @@ int mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok)
HA_CREATE_INFO create_info;
table->file->info(HA_STATUS_AUTO | HA_STATUS_NO_LOCK);
bzero((char*) &create_info,sizeof(create_info));
- create_info.auto_increment_value= table->file->auto_increment_value;
- create_info.table_charset=table->table_charset;
+ create_info.auto_increment_value= table->file->auto_increment_value;
+ create_info.default_table_charset= table->table_charset;
db_type table_type=table->db_type;
strmov(path,table->path);
@@ -605,7 +605,6 @@ int mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok)
}
bzero((char*) &create_info,sizeof(create_info));
- create_info.table_charset=table_list->table->table_charset;
*fn_ext(path)=0; // Remove the .frm extension
error= ha_create_table(path,&create_info,1) ? -1 : 0;
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index a55b801a0fc..50676ba6dd2 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -870,7 +870,7 @@ int yylex(void *arg, void *yythd)
case MY_LEX_COLON: // optional line terminator
if (yyPeek())
{
- if (((THD *)yythd)->client_capabilities & CLIENT_MULTI_QUERIES)
+ if (((THD *)yythd)->client_capabilities & CLIENT_MULTI_STATEMENTS)
{
lex->found_colon=(char*)lex->ptr;
((THD *)yythd)->server_status |= SERVER_MORE_RESULTS_EXISTS;
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index be931c56247..35132946df0 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -513,7 +513,7 @@ typedef struct st_lex
sql_exchange *exchange;
select_result *result;
Item *default_value;
- LEX_STRING *comment;
+ LEX_STRING *comment, name_and_length;
LEX_USER *grant_user;
gptr yacc_yyss,yacc_yyvs;
THD *thd;
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 321ac642e93..2a03add45bd 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -44,7 +44,6 @@
#define MIN_HANDSHAKE_SIZE 6
#endif /* HAVE_OPENSSL */
-extern "C" pthread_mutex_t THR_LOCK_keycache;
#ifdef SOLARIS
extern "C" int gethostname(char *name, int namelen);
#endif
@@ -1069,6 +1068,14 @@ void free_items(Item *item)
delete item;
}
+ /* This works because items are allocated with sql_alloc() */
+
+void cleanup_items(Item *item)
+{
+ for (; item ; item=item->next)
+ item->cleanup();
+}
+
int mysql_table_dump(THD* thd, char* db, char* tbl_name, int fd)
{
TABLE* table;
@@ -1576,6 +1583,23 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
kill_one_thread(thd,id);
break;
}
+ case COM_SET_OPTION:
+ {
+ statistic_increment(com_stat[SQLCOM_SET_OPTION], &LOCK_status);
+ enum_mysql_set_option command= (enum_mysql_set_option) uint2korr(packet);
+ switch (command) {
+ case MYSQL_OPTION_MULTI_STATEMENTS_ON:
+ thd->client_capabilities|= CLIENT_MULTI_STATEMENTS;
+ break;
+ case MYSQL_OPTION_MULTI_STATEMENTS_OFF:
+ thd->client_capabilities&= ~CLIENT_MULTI_STATEMENTS;
+ break;
+ default:
+ send_error(thd, ER_UNKNOWN_COM_ERROR);
+ break;
+ }
+ break;
+ }
case COM_DEBUG:
statistic_increment(com_other,&LOCK_status);
if (check_global_access(thd, SUPER_ACL))
@@ -1968,7 +1992,7 @@ mysql_execute_command(THD *thd)
check_access(thd, INDEX_ACL, tables->db,
&tables->grant.privilege, 0, 0))
goto error;
- res = mysql_assign_to_keycache(thd, tables);
+ res= mysql_assign_to_keycache(thd, tables, &lex->name_and_length);
break;
}
case SQLCOM_PRELOAD_KEYS:
@@ -2110,6 +2134,19 @@ mysql_execute_command(THD *thd)
break;
}
#endif
+ /*
+ If we are using SET CHARSET without DEFAULT, add an implicite
+ DEFAULT to not confuse old users. (This may change).
+ */
+ if ((lex->create_info.used_fields &
+ (HA_CREATE_USED_DEFAULT_CHARSET | HA_CREATE_USED_CHARSET)) ==
+ HA_CREATE_USED_CHARSET)
+ {
+ lex->create_info.used_fields&= ~HA_CREATE_USED_CHARSET;
+ lex->create_info.used_fields|= HA_CREATE_USED_DEFAULT_CHARSET;
+ lex->create_info.default_table_charset= lex->create_info.table_charset;
+ lex->create_info.table_charset= 0;
+ }
if (select_lex->item_list.elements) // With select
{
select_result *result;
@@ -2417,7 +2454,7 @@ mysql_execute_command(THD *thd)
bzero((char*) &create_info,sizeof(create_info));
create_info.db_type=DB_TYPE_DEFAULT;
create_info.row_type=ROW_TYPE_DEFAULT;
- create_info.table_charset=default_charset_info;
+ create_info.default_table_charset=default_charset_info;
res= mysql_alter_table(thd, NullS, NullS, &create_info,
tables, lex->create_list,
lex->key_list, lex->drop_list, lex->alter_list,
@@ -4628,15 +4665,24 @@ void kill_one_thread(THD *thd, ulong id)
static void refresh_status(void)
{
- pthread_mutex_lock(&THR_LOCK_keycache);
pthread_mutex_lock(&LOCK_status);
for (struct show_var_st *ptr=status_vars; ptr->name; ptr++)
{
if (ptr->type == SHOW_LONG)
- *(ulong*) ptr->value=0;
+ *(ulong*) ptr->value= 0;
+ else if (ptr->type == SHOW_KEY_CACHE_LONG)
+ {
+ /*
+ Reset value in 'default' key cache.
+ This needs to be recoded when we have thread specific key values
+ */
+ char *value= (((char*) sql_key_cache) +
+ (uint) ((char*) (ptr->value) -
+ (char*) &dflt_key_cache_var));
+ *(ulong*) value= 0;
+ }
}
pthread_mutex_unlock(&LOCK_status);
- pthread_mutex_unlock(&THR_LOCK_keycache);
}
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index 95a6ebb36fb..c2ebdeab5c2 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -1253,7 +1253,7 @@ store_create_info(THD *thd, TABLE *table, String *packet)
!(thd->variables.sql_mode & MODE_MYSQL323) &&
!(thd->variables.sql_mode & MODE_MYSQL40))
{
- packet->append(" CHARSET=", 9);
+ packet->append(" DEFAULT CHARSET=", 17);
packet->append(table->table_charset->csname);
if (!(table->table_charset->state & MY_CS_PRIMARY))
{
@@ -1589,6 +1589,7 @@ int mysqld_show(THD *thd, const char *wild, show_var_st *variables,
if (protocol->send_fields(&field_list,1))
DBUG_RETURN(1); /* purecov: inspected */
null_lex_str.str= 0; // For sys_var->value_ptr()
+ null_lex_str.length= 0;
pthread_mutex_lock(mutex);
for (; variables->name; variables++)
@@ -1848,6 +1849,10 @@ int mysqld_show(THD *thd, const char *wild, show_var_st *variables,
break;
#endif /* HAVE_OPENSSL */
+ case SHOW_KEY_CACHE_LONG:
+ value= (value-(char*) &dflt_key_cache_var)+ (char*) sql_key_cache;
+ end= int10_to_str(*(long*) value, buff, 10);
+ break;
case SHOW_UNDEF: // Show never happen
case SHOW_SYS:
break; // Return empty string
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 4571ae4877a..e75fec384e7 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -422,6 +422,12 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
for (field_no=0; (sql_field=it++) ; field_no++)
{
if (!sql_field->charset)
+ sql_field->charset= create_info->default_table_charset;
+ /*
+ table_charset is set in ALTER TABLE if we want change character set
+ for all varchar/char columns
+ */
+ if (create_info->table_charset)
sql_field->charset= create_info->table_charset;
sql_field->create_length_to_internal_length();
@@ -461,7 +467,9 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
{
/* Field redefined */
sql_field->sql_type= dup_field->sql_type;
- sql_field->charset= dup_field->charset ? dup_field->charset : create_info->table_charset;
+ sql_field->charset= (dup_field->charset ?
+ dup_field->charset :
+ create_info->default_table_charset);
sql_field->length= dup_field->length;
sql_field->pack_length= dup_field->pack_length;
sql_field->create_length_to_internal_length();
@@ -484,8 +492,8 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
it.rewind();
while ((sql_field=it++))
{
- if (!sql_field->charset)
- sql_field->charset = create_info->table_charset;
+ DBUG_ASSERT(sql_field->charset);
+
switch (sql_field->sql_type) {
case FIELD_TYPE_BLOB:
case FIELD_TYPE_MEDIUM_BLOB:
@@ -1625,11 +1633,25 @@ int mysql_optimize_table(THD* thd, TABLE_LIST* tables, HA_CHECK_OPT* check_opt)
-1 error
*/
-int mysql_assign_to_keycache(THD* thd, TABLE_LIST* tables)
+int mysql_assign_to_keycache(THD* thd, TABLE_LIST* tables,
+ LEX_STRING *key_cache_name)
{
+ HA_CHECK_OPT check_opt;
+ KEY_CACHE_VAR *key_cache;
DBUG_ENTER("mysql_assign_to_keycache");
- DBUG_RETURN(mysql_admin_table(thd, tables, 0,
- "assign_to_keycache", TL_READ, 0,
+
+ check_opt.init();
+ pthread_mutex_lock(&LOCK_global_system_variables);
+ if (!(key_cache= get_key_cache(key_cache_name)))
+ {
+ pthread_mutex_unlock(&LOCK_global_system_variables);
+ my_error(ER_UNKNOWN_KEY_CACHE, MYF(0), key_cache_name->str);
+ DBUG_RETURN(-1);
+ }
+ pthread_mutex_unlock(&LOCK_global_system_variables);
+ check_opt.key_cache= key_cache;
+ DBUG_RETURN(mysql_admin_table(thd, tables, &check_opt,
+ "assign_to_keycache", TL_READ_NO_INSERT, 0,
HA_OPEN_TO_ASSIGN, 0,
&handler::assign_to_keycache));
}
@@ -1642,78 +1664,34 @@ int mysql_assign_to_keycache(THD* thd, TABLE_LIST* tables)
reassign_keycache_tables()
thd Thread object
src_cache Reference to the key cache to clean up
- dest_name Name of the cache to assign tables to
- remove_fl Flag to destroy key cache when all tables are reassigned
+ dest_cache New key cache
- RETURN VALUES
+ NOTES
+ This is called when one sets a key cache size to zero, in which
+ case we have to move the tables associated to this key cache to
+ the "default" one.
+
+ One has to ensure that one never calls this function while
+ some other thread is changing the key cache. This is assured by
+ the caller setting src_cache->in_init before calling this function.
+
+ We don't delete the old key cache as there may still be pointers pointing
+ to it for a while after this function returns.
+
+ RETURN VALUES
0 ok
- -1 error
*/
-int reassign_keycache_tables(THD* thd, KEY_CACHE_VAR* src_cache,
- char *dest_name, bool remove_fl)
+int reassign_keycache_tables(THD *thd, KEY_CACHE_VAR *src_cache,
+ KEY_CACHE_VAR *dst_cache)
{
- int rc= 0;
- TABLE_LIST table;
- KEY_CACHE_ASMT *key_cache_asmt;
-
DBUG_ENTER("reassign_keycache_tables");
- VOID(pthread_mutex_lock(&LOCK_assign));
- for (key_cache_asmt= src_cache->assign_list ;
- key_cache_asmt;
- key_cache_asmt= key_cache_asmt->next)
- key_cache_asmt->to_reassign = 1;
- key_cache_asmt= src_cache->assign_list;
- while (key_cache_asmt)
- {
- if (key_cache_asmt->to_reassign)
- {
- bool refresh;
- VOID(pthread_mutex_unlock(&LOCK_assign));
- bzero((byte *) &table, sizeof(table));
- table.option= dest_name;
- table.db= key_cache_asmt->db_name;
- table.alias= table.real_name= key_cache_asmt->table_name;
- thd->open_options|= HA_OPEN_TO_ASSIGN;
- while (!(table.table=open_table(thd,table.db,
- table.real_name,table.alias,
- &refresh)) && refresh) ;
- thd->open_options&= ~HA_OPEN_TO_ASSIGN;
- if (!table.table)
- DBUG_RETURN(-1);
- table.table->pos_in_table_list= &table;
- key_cache_asmt->triggered= 1;
- rc= table.table->file->assign_to_keycache(thd, 0);
- close_thread_tables(thd);
- if (rc)
- DBUG_RETURN(rc);
- VOID(pthread_mutex_lock(&LOCK_assign));
- key_cache_asmt= src_cache->assign_list;
- continue;
- }
- else
- key_cache_asmt= key_cache_asmt->next;
- }
-
- while (src_cache->assignments)
- {
- struct st_my_thread_var *waiting_thread= my_thread_var;
- pthread_cond_wait(&waiting_thread->suspend, &LOCK_assign);
- }
- if (src_cache->extra_info)
- {
- my_free((char *) src_cache->extra_info, MYF(0));
- src_cache->extra_info= 0;
- }
-
- if (remove_fl && !src_cache->assign_list && src_cache != &dflt_key_cache_var)
- {
- end_key_cache(&src_cache->cache, 1);
- src_cache->buff_size= 0;
- src_cache->block_size= 0;
- }
- VOID(pthread_mutex_unlock(&LOCK_assign));
+ DBUG_ASSERT(src_cache != dst_cache);
+ DBUG_ASSERT(src_cache->in_init);
+ src_cache->buff_size= 0; // Free key cache
+ ha_resize_key_cache(src_cache);
+ ha_change_key_cache(src_cache, dst_cache);
DBUG_RETURN(0);
}
@@ -1766,7 +1744,6 @@ int mysql_create_like_table(THD* thd, TABLE_LIST* table,
char *src_db= thd->db;
char *src_table= table_ident->table.str;
int err;
-
DBUG_ENTER("mysql_create_like_table");
/*
@@ -2126,8 +2103,8 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
create_info->max_rows=table->max_rows;
if (!(used_fields & HA_CREATE_USED_AVG_ROW_LENGTH))
create_info->avg_row_length=table->avg_row_length;
- if (!(used_fields & HA_CREATE_USED_CHARSET))
- create_info->table_charset=table->table_charset;
+ if (!(used_fields & HA_CREATE_USED_DEFAULT_CHARSET))
+ create_info->default_table_charset= table->table_charset;
restore_record(table,default_values); // Empty record for DEFAULT
List_iterator<Alter_drop> drop_it(drop_list);
diff --git a/sql/sql_test.cc b/sql/sql_test.cc
index c14d30f8d34..449c43c24d1 100644
--- a/sql/sql_test.cc
+++ b/sql/sql_test.cc
@@ -28,9 +28,6 @@
#include <sys/malloc.h>
#endif
-/* Intern key cache variables */
-extern "C" pthread_mutex_t THR_LOCK_keycache;
-
static const char *lock_descriptions[] =
{
"No lock",
@@ -229,7 +226,9 @@ static int dl_compare(TABLE_LOCK_INFO *a,TABLE_LOCK_INFO *b)
return 1;
}
-static void push_locks_into_array(DYNAMIC_ARRAY *ar, THR_LOCK_DATA *data, bool wait, const char *text)
+
+static void push_locks_into_array(DYNAMIC_ARRAY *ar, THR_LOCK_DATA *data,
+ bool wait, const char *text)
{
if (data)
{
@@ -238,31 +237,34 @@ static void push_locks_into_array(DYNAMIC_ARRAY *ar, THR_LOCK_DATA *data, bool w
{
TABLE_LOCK_INFO table_lock_info;
table_lock_info.thread_id=table->in_use->thread_id;
- memcpy(table_lock_info.table_name, table->table_cache_key, table->key_length);
+ memcpy(table_lock_info.table_name, table->table_cache_key,
+ table->key_length);
table_lock_info.table_name[strlen(table_lock_info.table_name)]='.';
table_lock_info.waiting=wait;
table_lock_info.lock_text=text;
- table_lock_info.type=table->reginfo.lock_type; // obtainable also from THR_LOCK_DATA
+ // lock_type is also obtainable from THR_LOCK_DATA
+ table_lock_info.type=table->reginfo.lock_type;
VOID(push_dynamic(ar,(gptr) &table_lock_info));
}
}
}
-/*
- Regarding MERGE tables:
-For now, the best option is to use the common TABLE *pointer for all
-cases; The drawback is that for MERGE tables we will see many locks
-for the merge tables even if some of them are for individual tables.
-The way to solve this is to add to 'THR_LOCK' structure a pointer to
-the filename and use this when printing the data.
-(We can for now ignore this and just print the same name for all merge
-table parts; Please add the above as a comment to the display_lock
-function so that we can easily add this if we ever need this.
+/*
+ Regarding MERGE tables:
+
+ For now, the best option is to use the common TABLE *pointer for all
+ cases; The drawback is that for MERGE tables we will see many locks
+ for the merge tables even if some of them are for individual tables.
+ The way to solve this is to add to 'THR_LOCK' structure a pointer to
+ the filename and use this when printing the data.
+ (We can for now ignore this and just print the same name for all merge
+ table parts; Please add the above as a comment to the display_lock
+ function so that we can easily add this if we ever need this.
*/
-static void display_table_locks (void)
+static void display_table_locks(void)
{
LIST *list;
DYNAMIC_ARRAY saved_table_locks;
@@ -301,6 +303,36 @@ end:
}
+static int print_key_cache_status(const char *name, KEY_CACHE_VAR *key_cache)
+{
+ if (!key_cache->cache)
+ {
+ printf("%s: Not in use\n", name);
+ }
+ else
+ {
+ printf("%s\n\
+Buffer_size: %10lu\n\
+Block_size: %10lu\n\
+Division_limit: %10lu\n\
+Age_limit: %10lu\n\
+blocks used: %10lu\n\
+not flushed: %10lu\n\
+w_requests: %10lu\n\
+writes: %10lu\n\
+r_requests: %10lu\n\
+reads: %10lu\n\n",
+ name,
+ (ulong) key_cache->buff_size, key_cache->block_size,
+ key_cache->division_limit, key_cache->age_threshold,
+ key_cache->blocks_used,key_cache->blocks_changed,
+ key_cache->cache_w_requests,key_cache->cache_write,
+ key_cache->cache_r_requests,key_cache->cache_read);
+ }
+ return 0;
+}
+
+
void mysql_print_status(THD *thd)
{
char current_dir[FN_REFLEN];
@@ -320,19 +352,8 @@ void mysql_print_status(THD *thd)
/* Print key cache status */
if (thd)
thd->proc_info="key cache";
- pthread_mutex_lock(&THR_LOCK_keycache);
- printf("key_cache status:\n\
-blocks used:%10lu\n\
-not flushed:%10lu\n\
-w_requests: %10lu\n\
-writes: %10lu\n\
-r_requests: %10lu\n\
-reads: %10lu\n",
- dflt_key_cache_var.blocks_used,dflt_key_cache_var.blocks_changed,
- dflt_key_cache_var.cache_w_requests,dflt_key_cache_var.cache_write,
- dflt_key_cache_var.cache_r_requests,dflt_key_cache_var.cache_read);
- pthread_mutex_unlock(&THR_LOCK_keycache);
-
+ puts("\nKey caches:");
+ process_key_caches(print_key_cache_status);
if (thd)
thd->proc_info="status";
pthread_mutex_lock(&LOCK_status);
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index bb37c58004f..469fe932d92 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -588,7 +588,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
IDENT IDENT_QUOTED TEXT_STRING REAL_NUM FLOAT_NUM NUM LONG_NUM HEX_NUM
LEX_HOSTNAME ULONGLONG_NUM field_ident select_alias ident ident_or_text
UNDERSCORE_CHARSET IDENT_sys TEXT_STRING_sys TEXT_STRING_literal
- NCHAR_STRING opt_component
+ NCHAR_STRING opt_component key_cache_name
%type <lex_str_ptr>
opt_table_alias
@@ -925,7 +925,7 @@ create:
bzero((char*) &lex->create_info,sizeof(lex->create_info));
lex->create_info.options=$2 | $4;
lex->create_info.db_type= (enum db_type) lex->thd->variables.table_type;
- lex->create_info.table_charset= thd->variables.collation_database;
+ lex->create_info.default_table_charset= thd->variables.collation_database;
lex->name=0;
}
create2
@@ -950,7 +950,7 @@ create:
lex->col_list.empty();
}
| CREATE DATABASE opt_if_not_exists ident
- { Lex->create_info.table_charset=NULL; }
+ { Lex->create_info.default_table_charset=NULL; }
opt_create_database_options
{
LEX *lex=Lex;
@@ -1037,10 +1037,10 @@ create_database_options:
| create_database_options create_database_option {};
create_database_option:
- COLLATE_SYM collation_name_or_default
- { Lex->create_info.table_charset=$2; }
+ opt_default COLLATE_SYM collation_name_or_default
+ { Lex->create_info.default_table_charset=$3; }
| opt_default charset charset_name_or_default
- { Lex->create_info.table_charset=$3; }
+ { Lex->create_info.default_table_charset=$3; }
;
opt_table_options:
@@ -1100,11 +1100,21 @@ create_table_option:
table_list->next=0;
lex->create_info.used_fields|= HA_CREATE_USED_UNION;
}
- | opt_default charset opt_equal charset_name_or_default
+ | DEFAULT charset opt_equal charset_name_or_default
{
- Lex->create_info.table_charset= $4;
+ Lex->create_info.default_table_charset= $4;
+ Lex->create_info.used_fields|= HA_CREATE_USED_DEFAULT_CHARSET;
+ }
+ | charset opt_equal charset_name_or_default
+ {
+ Lex->create_info.table_charset= $3;
Lex->create_info.used_fields|= HA_CREATE_USED_CHARSET;
}
+ | DEFAULT COLLATE_SYM opt_equal collation_name_or_default
+ {
+ Lex->create_info.table_charset= $4;
+ Lex->create_info.used_fields|= HA_CREATE_USED_DEFAULT_CHARSET;
+ }
| COLLATE_SYM opt_equal collation_name_or_default
{
Lex->create_info.table_charset= $3;
@@ -1578,6 +1588,11 @@ key_or_index:
KEY_SYM {}
| INDEX {};
+opt_keys_or_index:
+ /* empty */ {}
+ | keys_or_index
+ ;
+
keys_or_index:
KEYS {}
| INDEX {}
@@ -1644,7 +1659,7 @@ alter:
lex->select_lex.db=lex->name=0;
bzero((char*) &lex->create_info,sizeof(lex->create_info));
lex->create_info.db_type= DB_TYPE_DEFAULT;
- lex->create_info.table_charset= thd->variables.collation_database;
+ lex->create_info.default_table_charset= thd->variables.collation_database;
lex->create_info.row_type= ROW_TYPE_NOT_USED;
lex->alter_keys_onoff=LEAVE_AS_IS;
lex->tablespace_op=NO_TABLESPACE_OP;
@@ -1990,13 +2005,12 @@ table_to_table:
};
keycache:
- CACHE_SYM INDEX
+ CACHE_SYM INDEX keycache_list IN_SYM key_cache_name
{
LEX *lex=Lex;
- lex->sql_command=SQLCOM_ASSIGN_TO_KEYCACHE;
+ lex->sql_command= SQLCOM_ASSIGN_TO_KEYCACHE;
+ lex->name_and_length= $5;
}
- keycache_list
- {}
;
keycache_list:
@@ -2004,30 +2018,22 @@ keycache_list:
| keycache_list ',' assign_to_keycache;
assign_to_keycache:
- table_ident cache_keys_spec IN_SYM ident
- {
- LEX *lex=Lex;
- SELECT_LEX *sel= &lex->select_lex;
- if (!sel->add_table_to_list(lex->thd, $1, NULL, 0,
- TL_READ,
- sel->get_use_index(),
- (List<String> *)0,
- &($4)))
- YYABORT;
- }
- |
- table_ident cache_keys_spec IN_SYM DEFAULT
+ table_ident cache_keys_spec
{
LEX *lex=Lex;
SELECT_LEX *sel= &lex->select_lex;
if (!sel->add_table_to_list(lex->thd, $1, NULL, 0,
TL_READ,
sel->get_use_index(),
- (List<String> *)0))
+ (List<String> *)0))
YYABORT;
}
;
+key_cache_name:
+ ident { $$= $1; }
+ | DEFAULT { $$ = default_key_cache_base; }
+
preload:
LOAD INDEX INTO CACHE_SYM
{
@@ -2056,19 +2062,22 @@ preload_keys:
;
cache_keys_spec:
- keys_or_index { Select->interval_list.empty(); }
+ { Select->interval_list.empty(); }
cache_key_list_or_empty
{
LEX *lex=Lex;
SELECT_LEX *sel= &lex->select_lex;
sel->use_index= sel->interval_list;
- sel->use_index_ptr= &sel->use_index;
}
;
cache_key_list_or_empty:
- /* empty */
- | '(' key_usage_list2 ')' {}
+ /* empty */ { Lex->select_lex.use_index_ptr= 0; }
+ | opt_keys_or_index '(' key_usage_list2 ')'
+ {
+ SELECT_LEX *sel= &Lex->select_lex;
+ sel->use_index_ptr= &sel->use_index;
+ }
;
opt_ignore_leaves:
diff --git a/sql/structs.h b/sql/structs.h
index 352823cceb2..37208e63400 100644
--- a/sql/structs.h
+++ b/sql/structs.h
@@ -173,7 +173,7 @@ enum SHOW_TYPE
SHOW_SSL_CTX_SESS_TIMEOUTS, SHOW_SSL_CTX_SESS_CACHE_FULL,
SHOW_SSL_GET_CIPHER_LIST,
#endif /* HAVE_OPENSSL */
- SHOW_RPL_STATUS, SHOW_SLAVE_RUNNING
+ SHOW_RPL_STATUS, SHOW_SLAVE_RUNNING, SHOW_KEY_CACHE_LONG
};
enum SHOW_COMP_OPTION { SHOW_OPTION_YES, SHOW_OPTION_NO, SHOW_OPTION_DISABLED};
diff --git a/sql/table.cc b/sql/table.cc
index 14853011510..e87cafd5275 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -1134,7 +1134,8 @@ File create_frm(register my_string name, uint reclength, uchar *fileinfo,
int2store(fileinfo+30,create_info->table_options);
fileinfo[32]=0; // No filename anymore
int4store(fileinfo+34,create_info->avg_row_length);
- fileinfo[38]= create_info->table_charset?create_info->table_charset->number:0;
+ fileinfo[38]= (create_info->default_table_charset ?
+ create_info->default_table_charset->number : 0);
fileinfo[40]= (uchar) create_info->row_type;
fileinfo[41]= (uchar) create_info->raid_type;
fileinfo[42]= (uchar) create_info->raid_chunks;
@@ -1165,7 +1166,8 @@ void update_create_info_from_table(HA_CREATE_INFO *create_info, TABLE *table)
create_info->raid_type=table->raid_type;
create_info->raid_chunks=table->raid_chunks;
create_info->raid_chunksize=table->raid_chunksize;
- create_info->table_charset=table->table_charset;
+ create_info->default_table_charset=table->table_charset;
+ create_info->table_charset= 0;
DBUG_VOID_RETURN;
}
diff --git a/sql/table.h b/sql/table.h
index b9c6a72bb09..4dcd24b2aff 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -56,30 +56,6 @@ typedef struct st_filesort_info
} FILESORT_INFO;
-/* Table key cache assignment descriptor */
-/*
- In future the similar structure is to be used for
- an assignment of an index to a key cache: the index name will be added.
- The name of the database catalog will be added as well.
- The descriptors for the current assignments are put in the
- assignment cache: assign_cache. If a table is not found in the cache
- it is considered assigned to the default key cache.
-*/
-typedef struct st_key_cache_asmt
-{
- char *db_name; /* db the table belongs to */
- char *table_name; /* the name of the table */
- char *table_key; /* key for the assignment cache */
- uint key_length; /* the length of this key */
- struct st_key_cache_var *key_cache; /* reference to the key cache */
- struct st_key_cache_asmt **prev; /* links in the chain all assignments */
- struct st_key_cache_asmt *next; /* to this cache */
- struct st_my_thread_var *queue; /* queue of requests for assignment */
- uint requests; /* number of current requests */
- bool to_reassign; /* marked when reassigning all cache */
- bool triggered; /* marked when assignment is triggered*/
-} KEY_CACHE_ASMT;
-
/* Table cache entry struct */
class Field_timestamp;
@@ -87,13 +63,11 @@ class Field_blob;
struct st_table {
handler *file;
- KEY_CACHE_VAR *key_cache; /* Ref to the key cache the table assigned to*/
- KEY_CACHE_ASMT *key_cache_asmt;/* Only when opened for key cache assignment */
- Field **field; /* Pointer to fields */
+ Field **field; /* Pointer to fields */
Field_blob **blob_field; /* Pointer to blob fields */
HASH name_hash; /* hash of field names */
byte *record[2]; /* Pointer to records */
- byte *default_values; /* Record with default values for INSERT */
+ byte *default_values; /* Default values for INSERT */
byte *insert_values; /* used by INSERT ... UPDATE */
uint fields; /* field count */
uint reclength; /* Recordlength */
diff --git a/sql/unireg.h b/sql/unireg.h
index 8d62959317d..2da25edd72a 100644
--- a/sql/unireg.h
+++ b/sql/unireg.h
@@ -68,7 +68,8 @@
#define MAX_DATETIME_FULL_WIDTH 29 /* YYYY-MM-DD HH:MM:SS.###### AM */
#define MAX_DATETIME_WIDTH 19 /* YYYY-MM-DD HH:MM:SS */
-#define MAX_TABLES (sizeof(table_map)*8-2) /* Max tables in join */
+#define MAX_TABLES (sizeof(table_map)*8-3) /* Max tables in join */
+#define PARAM_TABLE_BIT (((table_map) 1) << (sizeof(table_map)*8-3))
#define OUTER_REF_TABLE_BIT (((table_map) 1) << (sizeof(table_map)*8-2))
#define RAND_TABLE_BIT (((table_map) 1) << (sizeof(table_map)*8-1))
#define MAX_FIELDS 4096 /* Limit in the .frm file */
@@ -145,10 +146,10 @@
#define MTYP_NOEMPTY_BIT 128
/*
- * Minimum length pattern before Turbo Boyer-Moore is used
- * for SELECT "text" LIKE "%pattern%", excluding the two
- * wildcards in class Item_func_like.
- */
+ Minimum length pattern before Turbo Boyer-Moore is used
+ for SELECT "text" LIKE "%pattern%", excluding the two
+ wildcards in class Item_func_like.
+*/
#define MIN_TURBOBM_PATTERN_LEN 3
/*
@@ -160,7 +161,9 @@
#define BIN_LOG_HEADER_SIZE 4
#define FLOATING_POINT_BUFFER 331
- /* Include prototypes for unireg */
+#define DEFAULT_KEY_CACHE_NAME "default"
+
+/* Include prototypes for unireg */
#include "mysqld_error.h"
#include "structs.h" /* All structs we need */