summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <monty@mashka.mysql.fi>2003-11-18 13:47:27 +0200
committerunknown <monty@mashka.mysql.fi>2003-11-18 13:47:27 +0200
commite72124c4ccad5b390b84562389175dcd7355769c (patch)
tree0a23d90c946c5f05a8c160fc7c6ef3f05505fc79
parent61e682b8adafdfae736327fee4ea0263e1a0bd37 (diff)
downloadmariadb-git-e72124c4ccad5b390b84562389175dcd7355769c.tar.gz
CLIENT_MULTI_QUERIES -> CLIENT_MULTI_STATEMENTS
New multi-key-cache handling. This was needed becasue the old one didn't work reliable with MERGE tables. ALTER TABLE table_name ... CHARACTER SET ... now changes all char/varchar/text columns to the given character set (One must use ALTER TABLE ... DEFAULT CHARACTER SET ... to change the default character set) Fixed that have_compress is detected properly (fixes problems with func_compress.test on platforms without zlib) New syntax for CACHE INDEX ('keys' is optional if no index name is given and one mentions the key cache name only ones) Removed compiler warnings Added mysql_set_server_option() to allow clients like PHP to easaily set/reset the multi-statement flag. BUILD/compile-pentium-valgrind-max: Add test of isam client/mysql.cc: CLIENT_MULTI_QUERIES -> CLIENT_MULTI_STATEMENTS include/my_base.h: Remove HA_EXTRA_SET_KEY_CACHE include/my_no_pthread.h: Add defines to ignore rw-locks when running without threads include/my_sys.h: Added function for multi-key-caches include/myisam.h: Added function to handle multi-key-caches include/mysql.h: Added mysql_set_server_option include/mysql_com.h: CLIENT_MULTI_QUERIES -> CLIENT_MULTI_STATEMENTS Added enum_mysql_set_option include/mysqld_error.h: Added error message for unknown key cache innobase/srv/srv0start.c: Removed warning that is confused for MySQL users libmysql/libmysql.c: Added mysql_set_server_option() libmysql/libmysql.def: Added mysql_set_server_option() myisam/ft_nlq_search.c: Removed compiler warning myisam/ft_static.c: Removed compiler warning and fixed wrong return value myisam/mi_check.c: Clean up multi-key-cache usage myisam/mi_checksum.c: Removed not used variable myisam/mi_close.c: keycache -> key_cache myisam/mi_delete_all.c: keycache -> key_cache myisam/mi_extra.c: keycache -> key_cache Removed HA_EXTRA_SET_KEY_CACHE myisam/mi_keycache.c: Changed logic so that it's MyISAM that is responsible for assign tables to different key caches instead of the upper level myisam/mi_locking.c: Don't change key cache on unlock (must be done before) myisam/mi_open.c: Fetch key cache to use from multi_key_cache_search() myisam/mi_page.c: keycache -> key_cache myisam/mi_panic.c: keycache -> key_cache myisam/mi_preload.c: keycache -> key_cache myisam/mi_test1.c: Use KEY_CACHE_BLOCK_SIZE myisam/mi_test2.c: Always test resize_key_cache() myisam/mi_test3.c: Use KEY_CACHE_BLOCK_SIZE instead of 512 myisam/myisamchk.c: update for multiple key caches myisam/myisamdef.h: Remove reg_keycache Add unique_name_length for storing length of unique_file_name myisam/myisamlog.c: Change how end_key_cache() is called mysql-test/mysql-test-run.sh: Fixed web link Added name of failed test to abort row. mysql-test/r/alter_table.result: Testing of ALTER TABLE ... [DEFAULT] CHARACTER SET mysql-test/r/case.result: Update result for DEFAULT CHARSET... mysql-test/r/cast.result: Update result for DEFAULT CHARSET... mysql-test/r/create.result: Update result for DEFAULT CHARSET... mysql-test/r/ctype_collate.result: Update result for DEFAULT CHARSET... mysql-test/r/ctype_latin1_de.result: Update result for DEFAULT CHARSET... mysql-test/r/ctype_many.result: Update result for DEFAULT CHARSET... mysql-test/r/ctype_mb.result: Update result for DEFAULT CHARSET... mysql-test/r/ctype_recoding.result: Update result for DEFAULT CHARSET... mysql-test/r/ctype_ucs.result: Update result for DEFAULT CHARSET... mysql-test/r/derived.result: Use STRAIGHT_JOIN to make join order predictable mysql-test/r/fulltext.result: Update result for DEFAULT CHARSET... mysql-test/r/func_str.result: Update result for DEFAULT CHARSET... mysql-test/r/func_system.result: Update result for DEFAULT CHARSET... mysql-test/r/gis-rtree.result: Update result for DEFAULT CHARSET... mysql-test/r/innodb.result: Update result for DEFAULT CHARSET... mysql-test/r/key_cache.result: Update test for new key cache syntax. Added more tests mysql-test/r/merge.result: Update result for DEFAULT CHARSET... mysql-test/r/preload.result: New syntax mysql-test/r/show_check.result: Update result for DEFAULT CHARSET... mysql-test/r/sql_mode.result: Update result for DEFAULT CHARSET... mysql-test/r/subselect.result: Update result for DEFAULT CHARSET... mysql-test/r/type_blob.result: Update result for DEFAULT CHARSET... mysql-test/r/type_enum.result: Update result for DEFAULT CHARSET... mysql-test/r/type_nchar.result: Update result for DEFAULT CHARSET... mysql-test/r/type_set.result: Update result for DEFAULT CHARSET... mysql-test/r/union.result: Use STRAIGHT_JOIN to make join order predictable mysql-test/t/alter_table.test: Testing of ALTER TABLE ... [DEFAULT] CHARACTER SET mysql-test/t/ctype_many.test: Update result for DEFAULT CHARSET... mysql-test/t/derived.test: Use STRAIGHT_JOIN to make join order predictable mysql-test/t/isam.test: Use disable warnings for test loop mysql-test/t/join.test: Update test now when we only support 61 tables in join mysql-test/t/key_cache.test: Update test for new key cache syntax. Added more tests mysql-test/t/preload.test: Update for new syntax mysql-test/t/union.test: Use STRAIGHT_JOIN to make join order predictable mysys/Makefile.am: Added mf_keycaches.c mysys/hash.c: TRUE -> 1 mysys/mf_keycache.c: Removed compiler warnings Striped end space Fixed indentation and improved function comments TRUE -> 1 Changed parameters to end_key_cache() to make it easer to use Fixed bug when using key blocks size > 1024 bytes (First part of index file could be overwritten with wrong data) Split function flush_key_blocks into two functions to not get mutex used twice when called from flush_all_key_blocks() mysys/my_bitmap.c: More debugging Safe bitmap_free() Fixed indentation mysys/my_getopt.c: Ensure that we initialize option->value, option->max_value and value from GET_ASK_ADDR mysys/my_thr_init.c: Remove not used mutex THR_LOCK_keycache mysys/typelib.c: Fixed function comments sql-common/client.c: CLIENT_MULTI_QUERIES -> CLIENT_MULTI_STATEMENTS Fixed the multi_result flag is set also on SELECT;s sql/ha_myisam.cc: Fixed multiple key_cache handling (Now done on MyISAM level) sql/ha_myisammrg.cc: Fixed multiple key_cache handling (Now done on MyISAM level) sql/handler.cc: New multi key cache handling sql/handler.h: New multi key cache handling Added support for default character set sql/item.h: Added function cleanup() (Needed for prepared statements / cursors) sql/item_cmpfunc.h: Added cleanup function sql/item_func.cc: Indentation cleanup sql/mysql_priv.h: New multi-key-cache functions Removed LOCK_assign sql/mysqld.cc: New multi-key-cache handling Fixed that variable have_compress is set correctly sql/protocol.cc: SELECT didn't work reliable in multi-statements sql/set_var.cc: Support for new key cache variables sql/set_var.h: Support for new key cache variables sql/share/czech/errmsg.txt: New error messages sql/share/danish/errmsg.txt: New error messages sql/share/dutch/errmsg.txt: New error messages sql/share/english/errmsg.txt: New error messages sql/share/estonian/errmsg.txt: New error messages sql/share/french/errmsg.txt: New error messages sql/share/german/errmsg.txt: New error messages sql/share/greek/errmsg.txt: New error messages sql/share/hungarian/errmsg.txt: New error messages sql/share/italian/errmsg.txt: New error messages sql/share/japanese/errmsg.txt: New error messages sql/share/korean/errmsg.txt: New error messages sql/share/norwegian-ny/errmsg.txt: New error messages sql/share/norwegian/errmsg.txt: New error messages sql/share/polish/errmsg.txt: New error messages sql/share/portuguese/errmsg.txt: New error messages sql/share/romanian/errmsg.txt: New error messages sql/share/russian/errmsg.txt: New error messages sql/share/serbian/errmsg.txt: New error messages sql/share/slovak/errmsg.txt: New error messages sql/share/spanish/errmsg.txt: New error messages sql/share/swedish/errmsg.txt: New error messages sql/share/ukrainian/errmsg.txt: New error messages sql/sql_base.cc: Removed all key_cache handling (this is now done on MyISAM level) Change table_charset -> default_table_charset sql/sql_db.cc: table_charset -> default_table_charset sql/sql_delete.cc: table_charset -> default_table_charset sql/sql_lex.cc: CLIENT_MULTI_QUERIES -> CLIENT_MULTI_STATEMENTS sql/sql_lex.h: New option to store a name and length sql/sql_parse.cc: Support for mysql_set_server_option() Reset "default" keycache status variables in 'FLUSH STATUS' (Need to be improved later) sql/sql_show.cc: Add DEFAULT before CHARSET (for table character sets) Fetch key cache variables from 'sql_key_cache' sql/sql_table.cc: table_charset -> default_table_charset New multi-key-cache handling sql/sql_test.cc: Write information from all key caches sql/sql_yacc.yy: Changed syntax for CACHE INDEX ... Force user to use DEFAULT before database/table level character sets sql/structs.h: Added SHOW_KEY_CACHE_LONG (to get values from sql_key_cache) sql/table.cc: table_charset -> default_table_charset sql/table.h: New key cache handling (this is now done in mysys/mf_keycaches.c) sql/unireg.h: A
-rwxr-xr-xBUILD/compile-pentium-valgrind-max3
-rw-r--r--client/mysql.cc2
-rw-r--r--include/my_base.h10
-rw-r--r--include/my_no_pthread.h6
-rw-r--r--include/my_sys.h31
-rw-r--r--include/myisam.h10
-rw-r--r--include/mysql.h3
-rw-r--r--include/mysql_com.h12
-rw-r--r--include/mysqld_error.h3
-rw-r--r--innobase/srv/srv0start.c3
-rw-r--r--libmysql/libmysql.c14
-rw-r--r--libmysql/libmysql.def1
-rw-r--r--myisam/ft_nlq_search.c3
-rw-r--r--myisam/ft_static.c8
-rw-r--r--myisam/mi_check.c34
-rw-r--r--myisam/mi_checksum.c1
-rw-r--r--myisam/mi_close.c2
-rw-r--r--myisam/mi_delete_all.c2
-rw-r--r--myisam/mi_extra.c5
-rw-r--r--myisam/mi_keycache.c172
-rw-r--r--myisam/mi_locking.c15
-rw-r--r--myisam/mi_open.c2
-rw-r--r--myisam/mi_page.c9
-rw-r--r--myisam/mi_panic.c2
-rw-r--r--myisam/mi_preload.c6
-rw-r--r--myisam/mi_test1.c2
-rw-r--r--myisam/mi_test2.c8
-rw-r--r--myisam/mi_test3.c2
-rw-r--r--myisam/myisamchk.c8
-rw-r--r--myisam/myisamdef.h5
-rw-r--r--myisam/myisamlog.c4
-rw-r--r--mysql-test/mysql-test-run.sh4
-rw-r--r--mysql-test/r/alter_table.result23
-rw-r--r--mysql-test/r/case.result4
-rw-r--r--mysql-test/r/cast.result6
-rw-r--r--mysql-test/r/create.result20
-rw-r--r--mysql-test/r/ctype_collate.result8
-rw-r--r--mysql-test/r/ctype_latin1_de.result4
-rw-r--r--mysql-test/r/ctype_many.result12
-rw-r--r--mysql-test/r/ctype_mb.result10
-rw-r--r--mysql-test/r/ctype_recoding.result8
-rw-r--r--mysql-test/r/ctype_ucs.result2
-rw-r--r--mysql-test/r/derived.result8
-rw-r--r--mysql-test/r/fulltext.result2
-rw-r--r--mysql-test/r/func_str.result2
-rw-r--r--mysql-test/r/func_system.result2
-rw-r--r--mysql-test/r/gis-rtree.result4
-rw-r--r--mysql-test/r/innodb.result2
-rw-r--r--mysql-test/r/key_cache.result41
-rw-r--r--mysql-test/r/merge.result20
-rw-r--r--mysql-test/r/preload.result8
-rw-r--r--mysql-test/r/show_check.result18
-rw-r--r--mysql-test/r/sql_mode.result6
-rw-r--r--mysql-test/r/subselect.result8
-rw-r--r--mysql-test/r/type_blob.result2
-rw-r--r--mysql-test/r/type_enum.result4
-rw-r--r--mysql-test/r/type_nchar.result14
-rw-r--r--mysql-test/r/type_set.result4
-rw-r--r--mysql-test/r/union.result2
-rw-r--r--mysql-test/t/alter_table.test11
-rw-r--r--mysql-test/t/ctype_many.test2
-rw-r--r--mysql-test/t/derived.test8
-rw-r--r--mysql-test/t/isam.test2
-rw-r--r--mysql-test/t/join.test2
-rw-r--r--mysql-test/t/key_cache.test36
-rw-r--r--mysql-test/t/preload.test8
-rw-r--r--mysql-test/t/union.test2
-rw-r--r--mysys/Makefile.am2
-rw-r--r--mysys/hash.c2
-rw-r--r--mysys/mf_keycache.c349
-rw-r--r--mysys/mf_keycaches.c359
-rw-r--r--mysys/my_bitmap.c48
-rw-r--r--mysys/my_getopt.c109
-rw-r--r--mysys/my_thr_init.c4
-rw-r--r--mysys/typelib.c31
-rw-r--r--sql-common/client.c16
-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
125 files changed, 1725 insertions, 1187 deletions
diff --git a/BUILD/compile-pentium-valgrind-max b/BUILD/compile-pentium-valgrind-max
index 2e739ce9607..d1c84b93484 100755
--- a/BUILD/compile-pentium-valgrind-max
+++ b/BUILD/compile-pentium-valgrind-max
@@ -8,7 +8,8 @@ c_warnings="$c_warnings $debug_extra_warnings"
cxx_warnings="$cxx_warnings $debug_extra_warnings"
extra_configs="$pentium_configs $debug_configs"
-extra_configs="$extra_configs --with-berkeley-db --with-innodb --without-isam --with-embedded-server --with-openssl"
+# We want to test isam when building with valgrind
+extra_configs="$extra_configs --with-berkeley-db --with-innodb --with-isam --with-embedded-server --with-openssl"
. "$path/FINISH.sh"
diff --git a/client/mysql.cc b/client/mysql.cc
index c93875a55fc..af807d9fb60 100644
--- a/client/mysql.cc
+++ b/client/mysql.cc
@@ -2571,7 +2571,7 @@ sql_real_connect(char *host,char *database,char *user,char *password,
mysql_options(&mysql, MYSQL_SET_CHARSET_NAME, default_charset);
if (!mysql_real_connect(&mysql, host, user, password,
database, opt_mysql_port, opt_mysql_unix_port,
- connect_flag | CLIENT_MULTI_QUERIES))
+ connect_flag | CLIENT_MULTI_STATEMENTS))
{
if (!silent ||
(mysql_errno(&mysql) != CR_CONN_HOST_ERROR &&
diff --git a/include/my_base.h b/include/my_base.h
index 4c3e53c4573..a1744f37bc6 100644
--- a/include/my_base.h
+++ b/include/my_base.h
@@ -126,14 +126,14 @@ enum ha_extra_function {
HA_EXTRA_RESET_STATE, /* Reset positions */
HA_EXTRA_IGNORE_DUP_KEY, /* Dup keys don't rollback everything*/
HA_EXTRA_NO_IGNORE_DUP_KEY,
- HA_EXTRA_RETRIEVE_ALL_COLS, /* Instructs InnoDB to retrieve all
- columns, not just those where
- field->query_id is the same as the
- current query id */
+ /*
+ Instructs InnoDB to retrieve all columns, not just those where
+ field->query_id is the same as the current query id
+ */
+ HA_EXTRA_RETRIEVE_ALL_COLS,
HA_EXTRA_PREPARE_FOR_DELETE,
HA_EXTRA_PREPARE_FOR_UPDATE, /* Remove read cache if problems */
HA_EXTRA_PRELOAD_BUFFER_SIZE, /* Set buffer size for preloading */
- HA_EXTRA_SET_KEY_CACHE /* Set ref to assigned key cache */
};
/* The following is parameter to ha_panic() */
diff --git a/include/my_no_pthread.h b/include/my_no_pthread.h
index 0a034f78192..2c9cde65e78 100644
--- a/include/my_no_pthread.h
+++ b/include/my_no_pthread.h
@@ -27,5 +27,9 @@
#define pthread_mutex_lock(A)
#define pthread_mutex_unlock(A)
#define pthread_mutex_destroy(A)
-
+#define my_rwlock_init(A,B)
+#define rw_rdlock(A)
+#define rw_wrlock(A)
+#define rw_unlock(A)
+#define rwlock_destroy(A)
#endif
diff --git a/include/my_sys.h b/include/my_sys.h
index 6082b988822..25c450e5d2b 100644
--- a/include/my_sys.h
+++ b/include/my_sys.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000 MySQL AB
+/* Copyright (C) 2000-2003 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -111,6 +111,7 @@ extern int NEAR my_errno; /* Last error in mysys */
#define MY_WAIT_FOR_USER_TO_FIX_PANIC 60 /* in seconds */
#define MY_WAIT_GIVE_USER_A_MESSAGE 10 /* Every 10 times of prev */
#define MIN_COMPRESS_LENGTH 50 /* Don't compress small bl. */
+#define DFLT_INIT_HITS 3
/* root_alloc flags */
#define MY_KEEP_PREALLOC 1
@@ -510,13 +511,13 @@ typedef struct st_key_cache* KEY_CACHE_HANDLE;
/* Key cache variable structure */
/*
- The structure contains the parameters of a key cache that can
- be set and undated by regular set global statements.
- It also contains read-only statistics parameters.
- If the corresponding key cache data structure has been already
- created the variable contains the key cache handle.
- The variables are put into a named list called key_caches.
- At present the variables are only added to this list.
+ The structure contains the parameters of a key cache that can
+ be set and undated by regular set global statements.
+ It also contains read-only statistics parameters.
+ If the corresponding key cache data structure has been already
+ created the variable contains the key cache handle.
+ The variables are put into a named list called key_caches.
+ At present the variables are only added to this list.
*/
typedef struct st_key_cache_var
{
@@ -532,16 +533,16 @@ typedef struct st_key_cache_var
ulong cache_r_requests; /* number of read requests (read hits) */
ulong cache_read; /* number of reads from files to the cache */
int blocks; /* max number of blocks in the cache */
+ my_bool in_init; /* Set to 1 in MySQL during init/resize */
struct st_key_cache_asmt *assign_list; /* list of assignments to the cache */
int assignments; /* number of not completed assignments */
void (*action)(void *); /* optional call back function */
void *extra_info; /* ptr to extra info */
} KEY_CACHE_VAR;
-#define DEFAULT_KEY_CACHE_NAME "default"
+
extern KEY_CACHE_HANDLE *dflt_keycache;
extern KEY_CACHE_VAR dflt_key_cache_var;
-#define DFLT_INIT_HITS 3
#include <my_alloc.h>
@@ -701,7 +702,15 @@ extern int key_cache_write(KEY_CACHE_HANDLE keycache,
uint block_length,int force_write);
extern int flush_key_blocks(KEY_CACHE_HANDLE keycache,
int file, enum flush_type type);
-extern void end_key_cache(KEY_CACHE_HANDLE *pkeycache,my_bool cleanup);
+extern void end_key_cache(KEY_CACHE_HANDLE keycache, my_bool cleanup);
+extern my_bool multi_keycache_init(void);
+extern void multi_keycache_free(void);
+extern KEY_CACHE_HANDLE *multi_key_cache_search(byte *key, uint length);
+extern my_bool multi_key_cache_set(const byte *key, uint length,
+ KEY_CACHE_HANDLE *key_cache);
+extern void multi_key_cache_change(KEY_CACHE_HANDLE *old_data,
+ KEY_CACHE_HANDLE *new_data);
+
extern sig_handler my_set_alarm_variable(int signo);
extern void my_string_ptr_sort(void *base,uint items,size_s size);
extern void radixsort_for_str_ptr(uchar* base[], uint number_of_elements,
diff --git a/include/myisam.h b/include/myisam.h
index bf28168b7d7..52f2948aaef 100644
--- a/include/myisam.h
+++ b/include/myisam.h
@@ -324,7 +324,7 @@ typedef struct st_mi_check_param
sort_buffer_length,sort_key_blocks;
uint out_flag,warning_printed,error_printed,verbose;
uint opt_sort_key,total_files,max_level;
- uint testflag;
+ uint testflag, key_cache_block_size;
uint8 language;
my_bool using_global_keycache, opt_lock_memory, opt_follow_links;
my_bool retry_repair, force_sort, calc_checksum;
@@ -388,7 +388,6 @@ int change_to_newfile(const char * filename, const char * old_ext,
int lock_file(MI_CHECK *param, File file, my_off_t start, int lock_type,
const char *filetype, const char *filename);
void lock_memory(MI_CHECK *param);
-int flush_blocks(MI_CHECK *param, File file);
void update_auto_increment_key(MI_CHECK *param, MI_INFO *info,
my_bool repair);
int update_state_info(MI_CHECK *param, MI_INFO *info,uint update);
@@ -408,9 +407,10 @@ my_bool mi_test_if_sort_rep(MI_INFO *info, ha_rows rows, ulonglong key_map,
int mi_init_bulk_insert(MI_INFO *info, ulong cache_size, ha_rows rows);
void mi_flush_bulk_insert(MI_INFO *info, uint inx);
void mi_end_bulk_insert(MI_INFO *info);
-int mi_assign_to_keycache(MI_INFO *info, ulonglong key_map,
- KEY_CACHE_VAR *key_cache,
- pthread_mutex_t *assign_lock);
+int mi_assign_to_key_cache(MI_INFO *info, ulonglong key_map,
+ KEY_CACHE_VAR *key_cache);
+void mi_change_key_cache(KEY_CACHE_VAR *old_key_cache,
+ KEY_CACHE_VAR *new_key_cache);
int mi_preload(MI_INFO *info, ulonglong key_map, my_bool ignore_leaves);
#ifdef __cplusplus
diff --git a/include/mysql.h b/include/mysql.h
index f44d515478c..2098ed0516a 100644
--- a/include/mysql.h
+++ b/include/mysql.h
@@ -411,6 +411,9 @@ int STDCALL mysql_dump_debug_info(MYSQL *mysql);
int STDCALL mysql_refresh(MYSQL *mysql,
unsigned int refresh_options);
int STDCALL mysql_kill(MYSQL *mysql,unsigned long pid);
+int STDCALL mysql_set_server_option(MYSQL *mysql,
+ enum enum_mysql_set_option
+ option);
int STDCALL mysql_ping(MYSQL *mysql);
const char * STDCALL mysql_stat(MYSQL *mysql);
const char * STDCALL mysql_get_server_info(MYSQL *mysql);
diff --git a/include/mysql_com.h b/include/mysql_com.h
index f4b6114c8d4..3031b883e98 100644
--- a/include/mysql_com.h
+++ b/include/mysql_com.h
@@ -44,7 +44,7 @@ enum enum_server_command
COM_TIME, COM_DELAYED_INSERT, COM_CHANGE_USER, COM_BINLOG_DUMP,
COM_TABLE_DUMP, COM_CONNECT_OUT, COM_REGISTER_SLAVE,
COM_PREPARE, COM_EXECUTE, COM_LONG_DATA, COM_CLOSE_STMT,
- COM_RESET_STMT,
+ COM_RESET_STMT, COM_SET_OPTION,
COM_END /* Must be last */
};
@@ -116,7 +116,7 @@ enum enum_server_command
#define CLIENT_TRANSACTIONS 8192 /* Client knows about transactions */
#define CLIENT_RESERVED 16384 /* Old flag for 4.1 protocol */
#define CLIENT_SECURE_CONNECTION 32768 /* New 4.1 authentication */
-#define CLIENT_MULTI_QUERIES 65536 /* Enable/disable multiquery support */
+#define CLIENT_MULTI_STATEMENTS 65536 /* Enable/disable multi-stmt support */
#define CLIENT_MULTI_RESULTS 131072 /* Enable/disable multi-results */
#define CLIENT_REMEMBER_OPTIONS (1L << 31)
@@ -192,6 +192,7 @@ enum enum_field_types { MYSQL_TYPE_DECIMAL, MYSQL_TYPE_TINY,
};
/* For backward compatibility */
+#define CLIENT_MULTI_QUERIES CLIENT_MULTI_STATEMENTS
#define FIELD_TYPE_DECIMAL MYSQL_TYPE_DECIMAL
#define FIELD_TYPE_TINY MYSQL_TYPE_TINY
#define FIELD_TYPE_SHORT MYSQL_TYPE_SHORT
@@ -230,6 +231,13 @@ enum enum_field_types { MYSQL_TYPE_DECIMAL, MYSQL_TYPE_TINY,
#define MYSQL_TYPE_UINT24 -4
#endif
+/* options for mysql_set_option */
+enum enum_mysql_set_option
+{
+ MYSQL_OPTION_MULTI_STATEMENTS_ON,
+ MYSQL_OPTION_MULTI_STATEMENTS_OFF
+};
+
#define net_new_transaction(net) ((net)->pkt_nr=0)
#ifdef __cplusplus
diff --git a/include/mysqld_error.h b/include/mysqld_error.h
index 91b10ab578a..1ee88d90343 100644
--- a/include/mysqld_error.h
+++ b/include/mysqld_error.h
@@ -303,4 +303,5 @@
#define ER_CATALOG 1284
#define ER_WARN_QC_RESIZE 1285
#define ER_BAD_FT_COLUMN 1286
-#define ER_ERROR_MESSAGES 287
+#define ER_UNKNOWN_KEY_CACHE 1287
+#define ER_ERROR_MESSAGES 288
diff --git a/innobase/srv/srv0start.c b/innobase/srv/srv0start.c
index 067aec36627..3f375b66c4f 100644
--- a/innobase/srv/srv0start.c
+++ b/innobase/srv/srv0start.c
@@ -1629,9 +1629,6 @@ NetWare. */
srv_file_per_table = srv_file_per_table_original_value;
- fprintf(stderr,
-"TODO: make sure MySQL sets field->query_id right in prepare/execute\n");
-
return((int) DB_SUCCESS);
}
diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c
index 1cad02948e1..9c388f71314 100644
--- a/libmysql/libmysql.c
+++ b/libmysql/libmysql.c
@@ -1088,10 +1088,20 @@ mysql_refresh(MYSQL *mysql,uint options)
int STDCALL
mysql_kill(MYSQL *mysql,ulong pid)
{
- char buff[12];
+ char buff[4];
DBUG_ENTER("mysql_kill");
int4store(buff,pid);
- DBUG_RETURN(simple_command(mysql,COM_PROCESS_KILL,buff,4,0));
+ DBUG_RETURN(simple_command(mysql,COM_PROCESS_KILL,buff,sizeof(buff),0));
+}
+
+
+int STDCALL
+mysql_set_server_option(MYSQL *mysql, enum enum_mysql_set_option option)
+{
+ char buff[2];
+ DBUG_ENTER("mysql_set_server_option");
+ int2store(buff, (uint) option);
+ DBUG_RETURN(simple_command(mysql, COM_SET_OPTION, buff, sizeof(buff), 0));
}
diff --git a/libmysql/libmysql.def b/libmysql/libmysql.def
index 787aa645017..868275d1d5d 100644
--- a/libmysql/libmysql.def
+++ b/libmysql/libmysql.def
@@ -67,6 +67,7 @@ EXPORTS
mysql_init
mysql_insert_id
mysql_kill
+ mysql_set_server_option
mysql_list_dbs
mysql_list_fields
mysql_list_processes
diff --git a/myisam/ft_nlq_search.c b/myisam/ft_nlq_search.c
index a38c52704f7..6f86b0feb77 100644
--- a/myisam/ft_nlq_search.c
+++ b/myisam/ft_nlq_search.c
@@ -223,7 +223,8 @@ FT_INFO *ft_init_nlq_search(MI_INFO *info, uint keynr, byte *query,
if (flags & FT_EXPAND && ft_query_expansion_limit)
{
QUEUE best;
- init_queue(&best,ft_query_expansion_limit,0,0, &FT_DOC_cmp, 0);
+ init_queue(&best,ft_query_expansion_limit,0,0, (queue_compare) &FT_DOC_cmp,
+ 0);
tree_walk(&aio.dtree, (tree_walk_action) &walk_and_push,
&best, left_root_right);
while (best.elements)
diff --git a/myisam/ft_static.c b/myisam/ft_static.c
index 2edb86679e9..cf4f3d6a02a 100644
--- a/myisam/ft_static.c
+++ b/myisam/ft_static.c
@@ -53,13 +53,17 @@ const struct _ft_vft _ft_vft_boolean = {
ft_boolean_get_relevance, ft_boolean_reinit_search
};
+
FT_INFO *ft_init_search(uint flags, void *info, uint keynr,
byte *query, uint query_len, byte *record)
{
+ FT_INFO *res;
if (flags & FT_BOOL)
- ft_init_boolean_search((MI_INFO *)info, keynr, query, query_len);
+ res= ft_init_boolean_search((MI_INFO *)info, keynr, query, query_len);
else
- ft_init_nlq_search((MI_INFO *)info, keynr, query, query_len, flags, record);
+ res= ft_init_nlq_search((MI_INFO *)info, keynr, query, query_len, flags,
+ record);
+ return res;
}
const char *ft_stopword_file = 0;
diff --git a/myisam/mi_check.c b/myisam/mi_check.c
index a75ac75a2e9..cfdb696b60b 100644
--- a/myisam/mi_check.c
+++ b/myisam/mi_check.c
@@ -77,6 +77,7 @@ void myisamchk_init(MI_CHECK *param)
param->tmpfile_createflag=O_RDWR | O_TRUNC | O_EXCL;
param->myf_rw=MYF(MY_NABP | MY_WME | MY_WAIT_IF_FULL);
param->start_check_pos=0;
+ param->key_cache_block_size= KEY_CACHE_BLOCK_SIZE;
}
/* Check the status flags for the table */
@@ -241,7 +242,7 @@ static int check_k_link(MI_CHECK *param, register MI_INFO *info, uint nr)
if (next_link > info->state->key_file_length ||
next_link & (info->s->blocksize-1))
DBUG_RETURN(1);
- if (!(buff=key_cache_read(*info->s->keycache,
+ if (!(buff=key_cache_read(*info->s->key_cache,
info->s->kfile, next_link, DFLT_INIT_HITS,
(byte*) info->buff,
myisam_block_size, block_size, 1)))
@@ -272,7 +273,7 @@ int chk_size(MI_CHECK *param, register MI_INFO *info)
if (!(param->testflag & T_SILENT)) puts("- check file-size");
- flush_key_blocks(*info->s->keycache,
+ flush_key_blocks(*info->s->key_cache,
info->s->kfile, FLUSH_FORCE_WRITE); /* If called externally */
size=my_seek(info->s->kfile,0L,MY_SEEK_END,MYF(0));
@@ -1142,8 +1143,8 @@ int mi_repair(MI_CHECK *param, register MI_INFO *info,
param->testflag|=T_REP; /* for easy checking */
if (!param->using_global_keycache)
- VOID(init_key_cache(dflt_keycache,dflt_key_cache_var.block_size,
- param->use_buffers,&dflt_key_cache_var));
+ VOID(init_key_cache(dflt_keycache, param->key_cache_block_size,
+ param->use_buffers, &dflt_key_cache_var));
if (init_io_cache(&param->read_cache,info->dfile,
(uint) param->read_buffer_length,
@@ -1364,7 +1365,7 @@ err:
VOID(end_io_cache(&param->read_cache));
info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
VOID(end_io_cache(&info->rec_cache));
- got_error|=flush_blocks(param,share->kfile);
+ got_error|=flush_blocks(param, *share->key_cache, share->kfile);
if (!got_error && param->testflag & T_UNPACK)
{
share->state.header.options[0]&= (uchar) ~HA_OPTION_COMPRESS_RECORD;
@@ -1500,15 +1501,15 @@ void lock_memory(MI_CHECK *param __attribute__((unused)))
/* Flush all changed blocks to disk */
-int flush_blocks(MI_CHECK *param, File file)
+int flush_blocks(MI_CHECK *param, KEY_CACHE_HANDLE key_cache, File file)
{
- if (flush_key_blocks(*dflt_keycache,file,FLUSH_RELEASE))
+ if (flush_key_blocks(key_cache, file, FLUSH_RELEASE))
{
mi_check_print_error(param,"%d when trying to write bufferts",my_errno);
return(1);
}
if (!param->using_global_keycache)
- end_key_cache(dflt_keycache,1);
+ end_key_cache(key_cache,1);
return 0;
} /* flush_blocks */
@@ -1563,7 +1564,7 @@ int mi_sort_index(MI_CHECK *param, register MI_INFO *info, my_string name)
}
/* Flush key cache for this file if we are calling this outside myisamchk */
- flush_key_blocks(*share->keycache,share->kfile, FLUSH_IGNORE_CHANGED);
+ flush_key_blocks(*share->key_cache,share->kfile, FLUSH_IGNORE_CHANGED);
share->state.version=(ulong) time((time_t*) 0);
old_state= share->state; /* save state if not stored */
@@ -1873,7 +1874,7 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info,
Flush key cache for this file if we are calling this outside
myisamchk
*/
- flush_key_blocks(*share->keycache,share->kfile, FLUSH_IGNORE_CHANGED);
+ flush_key_blocks(*share->key_cache,share->kfile, FLUSH_IGNORE_CHANGED);
/* Clear the pointers to the given rows */
for (i=0 ; i < share->base.keys ; i++)
share->state.key_root[i]= HA_OFFSET_ERROR;
@@ -1883,7 +1884,7 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info,
}
else
{
- if (flush_key_blocks(*share->keycache,share->kfile, FLUSH_FORCE_WRITE))
+ if (flush_key_blocks(*share->key_cache,share->kfile, FLUSH_FORCE_WRITE))
goto err;
key_map= ~key_map; /* Create the missing keys */
}
@@ -2075,7 +2076,7 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info,
memcpy( &share->state.state, info->state, sizeof(*info->state));
err:
- got_error|= flush_blocks(param,share->kfile);
+ got_error|= flush_blocks(param, *share->key_cache, share->kfile);
VOID(end_io_cache(&info->rec_cache));
if (!got_error)
{
@@ -2236,7 +2237,7 @@ int mi_repair_parallel(MI_CHECK *param, register MI_INFO *info,
Flush key cache for this file if we are calling this outside
myisamchk
*/
- flush_key_blocks(*share->keycache,share->kfile, FLUSH_IGNORE_CHANGED);
+ flush_key_blocks(*share->key_cache,share->kfile, FLUSH_IGNORE_CHANGED);
/* Clear the pointers to the given rows */
for (i=0 ; i < share->base.keys ; i++)
share->state.key_root[i]= HA_OFFSET_ERROR;
@@ -2246,7 +2247,7 @@ int mi_repair_parallel(MI_CHECK *param, register MI_INFO *info,
}
else
{
- if (flush_key_blocks(*share->keycache,share->kfile, FLUSH_FORCE_WRITE))
+ if (flush_key_blocks(*share->key_cache,share->kfile, FLUSH_FORCE_WRITE))
goto err;
key_map= ~key_map; /* Create the missing keys */
}
@@ -2482,7 +2483,7 @@ int mi_repair_parallel(MI_CHECK *param, register MI_INFO *info,
memcpy(&share->state.state, info->state, sizeof(*info->state));
err:
- got_error|= flush_blocks(param,share->kfile);
+ got_error|= flush_blocks(param, *share->key_cache, share->kfile);
VOID(end_io_cache(&info->rec_cache));
if (!got_error)
{
@@ -3087,7 +3088,8 @@ int sort_write_record(MI_SORT_PARAM *sort_param)
(info->state->records % WRITE_COUNT) == 0)
{
char llbuff[22];
- printf("%s\r", llstr(info->state->records,llbuff)); VOID(fflush(stdout));
+ printf("%s\r", llstr(info->state->records,llbuff));
+ VOID(fflush(stdout));
}
}
DBUG_RETURN(0);
diff --git a/myisam/mi_checksum.c b/myisam/mi_checksum.c
index cdbb634c5ff..95338434211 100644
--- a/myisam/mi_checksum.c
+++ b/myisam/mi_checksum.c
@@ -27,7 +27,6 @@ ha_checksum mi_checksum(MI_INFO *info, const byte *buf)
for (i=info->s->base.fields ; i-- ; buf+=(rec++)->length)
{
const byte *pos;
- const byte *end;
ulong length;
switch (rec->type) {
case FIELD_BLOB:
diff --git a/myisam/mi_close.c b/myisam/mi_close.c
index 8e7fb497dfc..66d5b08bbc4 100644
--- a/myisam/mi_close.c
+++ b/myisam/mi_close.c
@@ -64,7 +64,7 @@ int mi_close(register MI_INFO *info)
if (flag)
{
if (share->kfile >= 0 &&
- flush_key_blocks(*share->keycache,share->kfile,
+ flush_key_blocks(*share->key_cache, share->kfile,
share->temporary ? FLUSH_IGNORE_CHANGED :
FLUSH_RELEASE))
error=my_errno;
diff --git a/myisam/mi_delete_all.c b/myisam/mi_delete_all.c
index 99873661feb..357df9ebe3e 100644
--- a/myisam/mi_delete_all.c
+++ b/myisam/mi_delete_all.c
@@ -53,7 +53,7 @@ int mi_delete_all_rows(MI_INFO *info)
If we are using delayed keys or if the user has done changes to the tables
since it was locked then there may be key blocks in the key cache
*/
- flush_key_blocks(*share->keycache, share->kfile, FLUSH_IGNORE_CHANGED);
+ flush_key_blocks(*share->key_cache, share->kfile, FLUSH_IGNORE_CHANGED);
if (my_chsize(info->dfile, 0, 0, MYF(MY_WME)) ||
my_chsize(share->kfile, share->base.keystart, 0, MYF(MY_WME)) )
goto err;
diff --git a/myisam/mi_extra.c b/myisam/mi_extra.c
index 8c7515550e7..327d795d17b 100644
--- a/myisam/mi_extra.c
+++ b/myisam/mi_extra.c
@@ -329,7 +329,7 @@ int mi_extra(MI_INFO *info, enum ha_extra_function function, void *extra_arg)
break;
case HA_EXTRA_FLUSH:
if (!share->temporary)
- flush_key_blocks(*share->keycache,share->kfile,FLUSH_KEEP);
+ flush_key_blocks(*share->key_cache, share->kfile, FLUSH_KEEP);
#ifdef HAVE_PWRITE
_mi_decrement_open_count(info);
#endif
@@ -362,9 +362,6 @@ int mi_extra(MI_INFO *info, enum ha_extra_function function, void *extra_arg)
case HA_EXTRA_PRELOAD_BUFFER_SIZE:
info->preload_buff_size= *((ulong *) extra_arg);
break;
- case HA_EXTRA_SET_KEY_CACHE:
- share->reg_keycache= share->keycache= (KEY_CACHE_HANDLE *) extra_arg;
- break;
case HA_EXTRA_KEY_CACHE:
case HA_EXTRA_NO_KEY_CACHE:
default:
diff --git a/myisam/mi_keycache.c b/myisam/mi_keycache.c
index 4b7d7d6b23f..c6fd1801740 100644
--- a/myisam/mi_keycache.c
+++ b/myisam/mi_keycache.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+/* Copyright (C) 2003 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -20,88 +20,136 @@
#include "myisamdef.h"
-
/*
Assign pages of the index file for a table to a key cache
SYNOPSIS
- mi_assign_to_keycache()
+ mi_assign_to_key_cache()
info open table
- map map of indexes to assign to the key cache
+ key_map map of indexes to assign to the key cache
key_cache_ptr pointer to the key cache handle
+ assign_lock Mutex to lock during assignment
- RETURN VALUE
- 0 if a success. error code - otherwise.
+ PREREQUESTS
+ One must have a READ lock or a WRITE lock on the table when calling
+ the function to ensure that there is no other writers to it.
- NOTES.
+ The caller must also ensure that one doesn't call this function from
+ two different threads with the same table.
+
+ NOTES
At present pages for all indexes must be assigned to the same key cache.
In future only pages for indexes specified in the key_map parameter
of the table will be assigned to the specified key cache.
-*/
-typedef struct st_assign_extra_info
-{
- pthread_mutex_t *lock;
- struct st_my_thread_var *waiting_thread;
-} ASSIGN_EXTRA_INFO;
+ RETURN VALUE
+ 0 If a success
+ # Error code
+*/
-static void remove_key_cache_assign(void *arg)
+int mi_assign_to_key_cache(MI_INFO *info,
+ ulonglong key_map __attribute__((unused)),
+ KEY_CACHE_VAR *key_cache)
{
- KEY_CACHE_VAR *key_cache= (KEY_CACHE_VAR *) arg;
- ASSIGN_EXTRA_INFO *extra_info= (ASSIGN_EXTRA_INFO *) key_cache->extra_info;
- struct st_my_thread_var *waiting_thread;
- pthread_mutex_t *lock= extra_info->lock;
- pthread_mutex_lock(lock);
- if (!(--key_cache->assignments) &&
- (waiting_thread = extra_info->waiting_thread))
+ int error= 0;
+ MYISAM_SHARE* share= info->s;
+ DBUG_ENTER("mi_assign_to_key_cache");
+ DBUG_PRINT("enter",("old_key_cache_handle: %lx new_key_cache_handle: %lx",
+ share->key_cache, &key_cache->cache));
+
+ /*
+ Skip operation if we didn't change key cache. This can happen if we
+ call this for all open instances of the same table
+ */
+ if (*share->key_cache == key_cache->cache)
+ DBUG_RETURN(0);
+
+ /*
+ First flush all blocks for the table in the old key cache.
+ This is to ensure that the disk is consistent with the data pages
+ in memory (which may not be the case if the table uses delayed_key_write)
+
+ Note that some other read thread may still fill in the key cache with
+ new blocks during this call and after, but this doesn't matter as
+ all threads will start using the new key cache for their next call to
+ myisam library and we know that there will not be any changed blocks
+ in the old key cache.
+ */
+
+ if (flush_key_blocks(*share->key_cache, share->kfile, FLUSH_REMOVE))
{
- my_free(extra_info, MYF(0));
- key_cache->extra_info= 0;
- if (waiting_thread != my_thread_var)
- pthread_cond_signal(&waiting_thread->suspend);
+ error= my_errno;
+ mi_mark_crashed(info); /* Mark that table must be checked */
}
- pthread_mutex_unlock(lock);
+
+ /*
+ Flush the new key cache for this file. This is needed to ensure
+ that there is no old blocks (with outdated data) left in the new key
+ cache from an earlier assign_to_keycache operation
+
+ (This can never fail as there is never any not written data in the
+ new key cache)
+ */
+ (void) flush_key_blocks(key_cache->cache, share->kfile, FLUSH_REMOVE);
+
+ /*
+ Tell all threads to use the new key cache
+ This should be seen at the lastes for the next call to an myisam function.
+ */
+ share->key_cache= &key_cache->cache;
+
+ /* store the key cache in the global hash structure for future opens */
+ if (multi_key_cache_set(share->unique_file_name, share->unique_name_length,
+ share->key_cache))
+ error= my_errno;
+ DBUG_RETURN(error);
}
-int mi_assign_to_keycache(MI_INFO *info, ulonglong key_map,
- KEY_CACHE_VAR *key_cache,
- pthread_mutex_t *assign_lock)
-{
- ASSIGN_EXTRA_INFO *extra_info;
- int error= 0;
- MYISAM_SHARE* share= info->s;
- DBUG_ENTER("mi_assign_to_keycache");
+/*
+ Change all MyISAM entries that uses one key cache to another key cache
- share->reg_keycache= &key_cache->cache;
- pthread_mutex_lock(assign_lock);
- if (!(extra_info= (ASSIGN_EXTRA_INFO *) key_cache->extra_info))
- {
- if (!(extra_info= (ASSIGN_EXTRA_INFO*) my_malloc(sizeof(ASSIGN_EXTRA_INFO),
- MYF(MY_WME | MY_ZEROFILL))))
- DBUG_RETURN(HA_ERR_OUT_OF_MEM);
- key_cache->extra_info= extra_info;
- key_cache->action= remove_key_cache_assign;
- extra_info->lock= assign_lock;
- }
- key_cache->assignments++;
- pthread_mutex_unlock(assign_lock);
-
- if (!(info->lock_type == F_WRLCK && share->w_locks))
- {
- if (flush_key_blocks(*share->keycache, share->kfile, FLUSH_REMOVE))
- {
- error=my_errno;
- mi_mark_crashed(info); /* Mark that table must be checked */
- }
- share->keycache= &key_cache->cache;
- }
- else
+ SYNOPSIS
+ mi_change_key_cache()
+ old_key_cache Old key cache
+ new_key_cache New key cache
+
+ NOTES
+ This is used when we delete one key cache.
+
+ To handle the case where some other threads tries to open an MyISAM
+ table associated with the to-be-deleted key cache while this operation
+ is running, we have to call 'multi_key_cache_change()' from this
+ function while we have a lock on the MyISAM table list structure.
+
+ This is safe as long as it's only MyISAM that is using this specific
+ key cache.
+*/
+
+
+void mi_change_key_cache(KEY_CACHE_VAR *old_key_cache,
+ KEY_CACHE_VAR *new_key_cache)
+{
+ LIST *pos;
+ DBUG_ENTER("mi_change_key_cache");
+
+ /*
+ Lock list to ensure that no one can close the table while we manipulate it
+ */
+ pthread_mutex_lock(&THR_LOCK_myisam);
+ for (pos=myisam_open_list ; pos ; pos=pos->next)
{
- extra_info->waiting_thread= my_thread_var;
+ MI_INFO *info= (MI_INFO*) pos->data;
+ MYISAM_SHARE *share= info->s;
+ if (share->key_cache == &old_key_cache->cache)
+ mi_assign_to_key_cache(info, (ulonglong) ~0, new_key_cache);
}
-
- DBUG_RETURN(error);
+ /*
+ We have to do the following call while we have the lock on the
+ MyISAM list structure to ensure that another thread is not trying to
+ open a new table that will be associted with the old key cache
+ */
+ multi_key_cache_change(&old_key_cache->cache, &new_key_cache->cache);
+ pthread_mutex_unlock(&THR_LOCK_myisam);
}
-
diff --git a/myisam/mi_locking.c b/myisam/mi_locking.c
index 6f996ab5abd..2056b018a16 100644
--- a/myisam/mi_locking.c
+++ b/myisam/mi_locking.c
@@ -34,7 +34,6 @@ int mi_lock_database(MI_INFO *info, int lock_type)
uint count;
MYISAM_SHARE *share=info->s;
uint flag;
- uint switch_fl= 0;
DBUG_ENTER("mi_lock_database");
DBUG_PRINT("info",("lock_type: %d", lock_type));
@@ -61,21 +60,13 @@ int mi_lock_database(MI_INFO *info, int lock_type)
else
count= --share->w_locks;
--share->tot_locks;
- /*
- During a key cache reassignment the current and registered
- key caches for the table are different.
- */
if (info->lock_type == F_WRLCK && !share->w_locks &&
- ((switch_fl= share->keycache != share->reg_keycache) ||
- !share->delay_key_write) &&
- flush_key_blocks(*share->keycache, share->kfile,
- switch_fl ? FLUSH_REMOVE : FLUSH_KEEP))
+ !share->delay_key_write && flush_key_blocks(*share->key_cache,
+ share->kfile,FLUSH_KEEP))
{
error=my_errno;
mi_mark_crashed(info); /* Mark that table must be checked */
}
- if (switch_fl)
- share->keycache= share->reg_keycache;
if (info->opt_flag & (READ_CACHE_USED | WRITE_CACHE_USED))
{
if (end_io_cache(&info->rec_cache))
@@ -398,7 +389,7 @@ int _mi_test_if_changed(register MI_INFO *info)
{ /* Keyfile has changed */
DBUG_PRINT("info",("index file changed"));
if (share->state.process != share->this_process)
- VOID(flush_key_blocks(*share->keycache,share->kfile,FLUSH_RELEASE));
+ VOID(flush_key_blocks(*share->key_cache, share->kfile, FLUSH_RELEASE));
share->last_process=share->state.process;
info->last_unique= share->state.unique;
info->last_loop= share->state.update_count;
diff --git a/myisam/mi_open.c b/myisam/mi_open.c
index 0b4e8681bdd..d5492ae5e35 100644
--- a/myisam/mi_open.c
+++ b/myisam/mi_open.c
@@ -104,6 +104,7 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
share_buff.state.rec_per_key_part=rec_per_key_part;
share_buff.state.key_root=key_root;
share_buff.state.key_del=key_del;
+ share_buff.key_cache= multi_key_cache_search(name_buff, strlen(name_buff));
if ((kfile=my_open(name_buff,(open_mode=O_RDWR) | O_SHARE,MYF(0))) < 0)
{
@@ -293,6 +294,7 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
(char*) key_del, (sizeof(my_off_t) *
share->state.header.max_block_size));
strmov(share->unique_file_name, name_buff);
+ share->unique_name_length= strlen(name_buff);
strmov(share->index_file_name, index_name);
strmov(share->data_file_name, data_name);
diff --git a/myisam/mi_page.c b/myisam/mi_page.c
index 72aaac5d381..0aae267e05e 100644
--- a/myisam/mi_page.c
+++ b/myisam/mi_page.c
@@ -32,7 +32,7 @@ uchar *_mi_fetch_keypage(register MI_INFO *info, MI_KEYDEF *keyinfo,
DBUG_ENTER("_mi_fetch_keypage");
DBUG_PRINT("enter",("page: %ld",page));
- tmp=(uchar*) key_cache_read(*info->s->keycache,
+ tmp=(uchar*) key_cache_read(*info->s->key_cache,
info->s->kfile, page, level, (byte*) buff,
(uint) keyinfo->block_length,
(uint) keyinfo->block_length,
@@ -52,6 +52,7 @@ uchar *_mi_fetch_keypage(register MI_INFO *info, MI_KEYDEF *keyinfo,
{
DBUG_PRINT("error",("page %lu had wrong page length: %u",
(ulong) page, page_size));
+ DBUG_DUMP("page", tmp, keyinfo->block_length);
info->last_keypage = HA_OFFSET_ERROR;
my_errno = HA_ERR_CRASHED;
tmp = 0;
@@ -94,7 +95,7 @@ int _mi_write_keypage(register MI_INFO *info, register MI_KEYDEF *keyinfo,
length=keyinfo->block_length;
}
#endif
- DBUG_RETURN((key_cache_write(*info->s->keycache,
+ DBUG_RETURN((key_cache_write(*info->s->key_cache,
info->s->kfile,page, level, (byte*) buff,length,
(uint) keyinfo->block_length,
(int) ((info->lock_type != F_UNLCK) ||
@@ -116,7 +117,7 @@ int _mi_dispose(register MI_INFO *info, MI_KEYDEF *keyinfo, my_off_t pos,
info->s->state.key_del[keyinfo->block_size]=pos;
mi_sizestore(buff,old_link);
info->s->state.changed|= STATE_NOT_SORTED_PAGES;
- DBUG_RETURN(key_cache_write(*info->s->keycache,
+ DBUG_RETURN(key_cache_write(*info->s->key_cache,
info->s->kfile, pos , level, buff,
sizeof(buff),
(uint) keyinfo->block_length,
@@ -145,7 +146,7 @@ my_off_t _mi_new(register MI_INFO *info, MI_KEYDEF *keyinfo, int level)
}
else
{
- if (!key_cache_read(*info->s->keycache,
+ if (!key_cache_read(*info->s->key_cache,
info->s->kfile, pos, level,
buff,
(uint) sizeof(buff),
diff --git a/myisam/mi_panic.c b/myisam/mi_panic.c
index f1d1d839fcd..cefb3423ccc 100644
--- a/myisam/mi_panic.c
+++ b/myisam/mi_panic.c
@@ -48,7 +48,7 @@ int mi_panic(enum ha_panic_function flag)
if (info->s->options & HA_OPTION_READ_ONLY_DATA)
break;
#endif
- if (flush_key_blocks(*info->s->keycache,info->s->kfile,FLUSH_RELEASE))
+ if (flush_key_blocks(*info->s->key_cache, info->s->kfile, FLUSH_RELEASE))
error=my_errno;
if (info->opt_flag & WRITE_CACHE_USED)
if (flush_io_cache(&info->rec_cache))
diff --git a/myisam/mi_preload.c b/myisam/mi_preload.c
index dc4fff5700a..3219c00b0e2 100644
--- a/myisam/mi_preload.c
+++ b/myisam/mi_preload.c
@@ -69,7 +69,7 @@ int mi_preload(MI_INFO *info, ulonglong key_map, my_bool ignore_leaves)
if (!(buff= (uchar *) my_malloc(length, MYF(MY_WME))))
DBUG_RETURN(my_errno= HA_ERR_OUT_OF_MEM);
- if (flush_key_blocks(*share->keycache,share->kfile, FLUSH_RELEASE))
+ if (flush_key_blocks(*share->key_cache,share->kfile, FLUSH_RELEASE))
goto err;
do
@@ -87,7 +87,7 @@ int mi_preload(MI_INFO *info, ulonglong key_map, my_bool ignore_leaves)
{
if (mi_test_if_nod(buff))
{
- if (key_cache_insert(*share->keycache,
+ if (key_cache_insert(*share->key_cache,
share->kfile, pos, DFLT_INIT_HITS,
(byte*) buff, block_length))
goto err;
@@ -99,7 +99,7 @@ int mi_preload(MI_INFO *info, ulonglong key_map, my_bool ignore_leaves)
}
else
{
- if (key_cache_insert(*share->keycache,
+ if (key_cache_insert(*share->key_cache,
share->kfile, pos, DFLT_INIT_HITS,
(byte*) buff, length))
goto err;
diff --git a/myisam/mi_test1.c b/myisam/mi_test1.c
index ec68e23c0c2..c1b76408a7c 100644
--- a/myisam/mi_test1.c
+++ b/myisam/mi_test1.c
@@ -50,7 +50,7 @@ int main(int argc,char *argv[])
MY_INIT(argv[0]);
my_init();
if (key_cacheing)
- init_key_cache(dflt_keycache,512,IO_SIZE*16,0);
+ init_key_cache(dflt_keycache,KEY_CACHE_BLOCK_SIZE,IO_SIZE*16,0);
get_options(argc,argv);
exit(run_test("test1"));
diff --git a/myisam/mi_test2.c b/myisam/mi_test2.c
index 5a40db3171d..5918a2485b0 100644
--- a/myisam/mi_test2.c
+++ b/myisam/mi_test2.c
@@ -49,7 +49,7 @@ static int verbose=0,testflag=0,
static int pack_seg=HA_SPACE_PACK,pack_type=HA_PACK_KEY,remove_count=-1,
create_flag=0;
static ulong key_cache_size=IO_SIZE*16;
-static uint key_cache_block_size=IO_SIZE;
+static uint key_cache_block_size= KEY_CACHE_BLOCK_SIZE;
static uint keys=MYISAM_KEYS,recant=1000;
static uint use_blob=0;
@@ -274,9 +274,9 @@ int main(int argc, char *argv[])
puts("got error from mi_extra(HA_EXTRA_NO_CACHE)");
goto end;
}
- if (key_cacheing)
- resize_key_cache(dflt_keycache,key_cache_block_size,key_cache_size*2);
}
+ if (key_cacheing)
+ resize_key_cache(dflt_keycache,key_cache_block_size,key_cache_size*2);
if (!silent)
printf("- Delete\n");
@@ -829,7 +829,7 @@ reads: %10lu\n",
my_cache_r_requests, my_cache_read);
#endif
}
- end_key_cache(dflt_keycache,1);
+ end_key_cache(*dflt_keycache,1);
if (blob_buffer)
my_free(blob_buffer,MYF(0));
my_end(silent ? MY_CHECK_ERROR : MY_CHECK_ERROR | MY_GIVE_INFO);
diff --git a/myisam/mi_test3.c b/myisam/mi_test3.c
index 866c6299fac..baeaba7bf24 100644
--- a/myisam/mi_test3.c
+++ b/myisam/mi_test3.c
@@ -177,7 +177,7 @@ void start_test(int id)
exit(1);
}
if (key_cacheing && rnd(2) == 0)
- init_key_cache(dflt_keycache,512,65536L,0);
+ init_key_cache(dflt_keycache, KEY_CACHE_BLOCK_SIZE, 65536L,0);
printf("Process %d, pid: %d\n",id,getpid()); fflush(stdout);
for (error=i=0 ; i < tests && !error; i++)
diff --git a/myisam/myisamchk.c b/myisam/myisamchk.c
index 59cc26b198b..605baa14582 100644
--- a/myisam/myisamchk.c
+++ b/myisam/myisamchk.c
@@ -715,6 +715,7 @@ static void get_options(register int *argc,register char ***argv)
exit(1);
check_param.tmpdir=&myisamchk_tmpdir;
+ check_param.key_cache_block_size= opt_key_cache_block_size;
if (set_charset_name)
if (!(set_charset=get_charset_by_name(set_charset_name, MYF(MY_WME))))
@@ -1046,7 +1047,7 @@ static int myisamchk(MI_CHECK *param, my_string filename)
HA_OPTION_COMPRESS_RECORD)) ||
(param->testflag & (T_EXTEND | T_MEDIUM)))
error|=chk_data_link(param, info, param->testflag & T_EXTEND);
- error|=flush_blocks(param,share->kfile);
+ error|=flush_blocks(param, *share->key_cache, share->kfile);
VOID(end_io_cache(&param->read_cache));
}
if (!error)
@@ -1455,7 +1456,7 @@ static int mi_sort_records(MI_CHECK *param,
if (share->state.key_root[sort_key] == HA_OFFSET_ERROR)
DBUG_RETURN(0); /* Nothing to do */
- init_key_cache(dflt_keycache,opt_key_cache_block_size,param->use_buffers,
+ init_key_cache(dflt_keycache, opt_key_cache_block_size, param->use_buffers,
&dflt_key_cache_var);
if (init_io_cache(&info->rec_cache,-1,(uint) param->write_buffer_length,
WRITE_CACHE,share->pack.header_length,1,
@@ -1570,7 +1571,8 @@ err:
my_free(sort_info.buff,MYF(MY_ALLOW_ZERO_PTR));
sort_info.buff=0;
share->state.sortkey=sort_key;
- DBUG_RETURN(flush_blocks(param, share->kfile) | got_error);
+ DBUG_RETURN(flush_blocks(param, *share->key_cache, share->kfile) |
+ got_error);
} /* sort_records */
diff --git a/myisam/myisamdef.h b/myisam/myisamdef.h
index c23959d995c..4f1bed5d50a 100644
--- a/myisam/myisamdef.h
+++ b/myisam/myisamdef.h
@@ -166,8 +166,7 @@ typedef struct st_mi_isam_share { /* Shared between opens */
char *data_file_name, /* Resolved path names from symlinks */
*index_file_name;
byte *file_map; /* mem-map of file if possible */
- KEY_CACHE_HANDLE *keycache; /* ref to the current key cache */
- KEY_CACHE_HANDLE *reg_keycache; /* ref to the registered key cache */
+ KEY_CACHE_HANDLE *key_cache; /* ref to the current key cache */
MI_DECODE_TREE *decode_trees;
uint16 *decode_tables;
int (*read_record)(struct st_myisam_info*, my_off_t, byte*);
@@ -188,6 +187,7 @@ typedef struct st_mi_isam_share { /* Shared between opens */
ulong max_pack_length;
ulong state_diff_length;
uint rec_reflength; /* rec_reflength in use now */
+ uint unique_name_length;
File kfile; /* Shared keyfile */
File data_file; /* Shared data file */
int mode; /* mode of file on open */
@@ -713,6 +713,7 @@ int thr_write_keys(MI_SORT_PARAM *sort_param);
#ifdef THREAD
pthread_handler_decl(thr_find_all_keys,arg);
#endif
+int flush_blocks(MI_CHECK *param, KEY_CACHE_HANDLE key_cache, File file);
int sort_write_record(MI_SORT_PARAM *sort_param);
int _create_index_by_sort(MI_SORT_PARAM *info,my_bool no_messages, ulong);
diff --git a/myisam/myisamlog.c b/myisam/myisamlog.c
index 9b987364521..fbe8b675821 100644
--- a/myisam/myisamlog.c
+++ b/myisam/myisamlog.c
@@ -648,7 +648,7 @@ static int examine_log(my_string file_name, char **table_names)
goto end;
}
}
- end_key_cache(dflt_keycache,1);
+ end_key_cache(*dflt_keycache,1);
delete_tree(&tree);
VOID(end_io_cache(&cache));
VOID(my_close(file,MYF(0)));
@@ -668,7 +668,7 @@ static int examine_log(my_string file_name, char **table_names)
llstr(isamlog_filepos,llbuff)));
fflush(stderr);
end:
- end_key_cache(dflt_keycache,1);
+ end_key_cache(*dflt_keycache, 1);
delete_tree(&tree);
VOID(end_io_cache(&cache));
VOID(my_close(file,MYF(0)));
diff --git a/mysql-test/mysql-test-run.sh b/mysql-test/mysql-test-run.sh
index 46d6819b819..f908ffeb2a6 100644
--- a/mysql-test/mysql-test-run.sh
+++ b/mysql-test/mysql-test-run.sh
@@ -575,7 +575,7 @@ show_failed_diff ()
$DIFF -c $result_file $reject_file
echo "-------------------------------------------------------"
echo "Please follow the instructions outlined at"
- echo "http://www.mysql.com/doc/R/e/Reporting_mysqltest_bugs.html"
+ echo "http://www.mysql.com/doc/en/Reporting_mysqltest_bugs.html"
echo "to find the reason to this problem and how to report this."
fi
}
@@ -1311,7 +1311,7 @@ run_testcase ()
show_failed_diff $tname
$ECHO
if [ x$FORCE != x1 ] ; then
- $ECHO "Aborting. To continue, re-run with '--force'."
+ $ECHO "Aborting becasue $tname failed. To continue, re-run with '--force'."
$ECHO
if [ -z "$DO_GDB" ] && [ -z "$USE_RUNNING_SERVER" ] && [ -z "$DO_DDD" ]
then
diff --git a/mysql-test/r/alter_table.result b/mysql-test/r/alter_table.result
index 9d3a0461f9f..b82255bf652 100644
--- a/mysql-test/r/alter_table.result
+++ b/mysql-test/r/alter_table.result
@@ -319,6 +319,29 @@ alter table t1 change a a char(10) character set koi8r;
select a,hex(a) from t1;
a hex(a)
ÔÅÓÔ D4C5D3D4
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` char(10) character set koi8r default NULL
+) TYPE=MyISAM DEFAULT CHARSET=latin1
+alter table t1 DEFAULT CHARACTER SET latin1;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` char(10) character set koi8r default NULL
+) TYPE=MyISAM DEFAULT CHARSET=latin1
+alter table t1 CHARACTER SET latin1;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` char(10) default NULL
+) TYPE=MyISAM DEFAULT CHARSET=latin1
+alter table t1 DEFAULT CHARACTER SET cp1251;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` char(10) character set latin1 default NULL
+) TYPE=MyISAM DEFAULT CHARSET=cp1251
drop table t1;
CREATE TABLE t1 (
Host varchar(16) binary NOT NULL default '',
diff --git a/mysql-test/r/case.result b/mysql-test/r/case.result
index 4aab3defa2b..9b03422f54c 100644
--- a/mysql-test/r/case.result
+++ b/mysql-test/r/case.result
@@ -103,7 +103,7 @@ t1 CREATE TABLE `t1` (
`c6` char(3) default NULL,
`c7` double(3,1) default NULL,
`c8` double(3,1) default NULL
-) TYPE=MyISAM CHARSET=latin1
+) TYPE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
SELECT CASE
WHEN 1
@@ -150,5 +150,5 @@ t1 CREATE TABLE `t1` (
`COALESCE(1,'1')` char(1) NOT NULL default '',
`COALESCE(1.1,'1')` char(3) NOT NULL default '',
`COALESCE('a' COLLATE latin1_bin,'b')` char(1) character set latin1 collate latin1_bin NOT NULL default ''
-) TYPE=MyISAM CHARSET=latin1
+) TYPE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
diff --git a/mysql-test/r/cast.result b/mysql-test/r/cast.result
index 974a79580ae..43afd02169c 100644
--- a/mysql-test/r/cast.result
+++ b/mysql-test/r/cast.result
@@ -45,7 +45,7 @@ show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`t` char(4) character set cp1251 NOT NULL default ''
-) TYPE=MyISAM CHARSET=latin1
+) TYPE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
select
cast(_latin1'ab' AS char) as c1,
@@ -72,7 +72,7 @@ t1 CREATE TABLE `t1` (
`c3` char(2) binary NOT NULL default '',
`c4` char(2) binary NOT NULL default '',
`c5` char(2) binary NOT NULL default ''
-) TYPE=MyISAM CHARSET=latin1
+) TYPE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
select
cast(_koi8r'ÆÇ' AS nchar) as c1,
@@ -99,7 +99,7 @@ t1 CREATE TABLE `t1` (
`c3` char(2) character set utf8 NOT NULL default '',
`c4` char(2) character set utf8 NOT NULL default '',
`c5` char(2) character set utf8 NOT NULL default ''
-) TYPE=MyISAM CHARSET=latin1
+) TYPE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
select cast("2001-1-1" as date) = "2001-01-01";
cast("2001-1-1" as date) = "2001-01-01"
diff --git a/mysql-test/r/create.result b/mysql-test/r/create.result
index d61614180b3..28f06f0bf47 100644
--- a/mysql-test/r/create.result
+++ b/mysql-test/r/create.result
@@ -179,7 +179,7 @@ t1 CREATE TABLE `t1` (
KEY `b_29` (`b`),
KEY `b_30` (`b`),
KEY `b_31` (`b`)
-) TYPE=MyISAM CHARSET=latin1
+) TYPE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
create table t1 select if(1,'1','0'), month("2002-08-02");
drop table t1;
@@ -197,7 +197,7 @@ show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` int(11) NOT NULL default '0'
-) TYPE=HEAP CHARSET=latin1
+) TYPE=HEAP DEFAULT CHARSET=latin1
drop table t1;
SET SESSION table_type="gemini";
SELECT @@table_type;
@@ -210,7 +210,7 @@ show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` int(11) NOT NULL default '0'
-) TYPE=MyISAM CHARSET=latin1
+) TYPE=MyISAM DEFAULT CHARSET=latin1
SET SESSION table_type=default;
drop table t1;
create table t1 ( k1 varchar(2), k2 int, primary key(k1,k2));
@@ -275,7 +275,7 @@ Table Create Table
t3 CREATE TABLE `t3` (
`id` int(11) NOT NULL default '0',
`name` char(20) default NULL
-) TYPE=MyISAM CHARSET=latin1
+) TYPE=MyISAM DEFAULT CHARSET=latin1
select * from t3;
id name
create table if not exists t3 like t1;
@@ -289,7 +289,7 @@ show create table t3;
Table Create Table
t3 CREATE TEMPORARY TABLE `t3` (
`id` int(11) NOT NULL default '0'
-) TYPE=MyISAM CHARSET=latin1
+) TYPE=MyISAM DEFAULT CHARSET=latin1
select * from t3;
id
drop table t3;
@@ -298,7 +298,7 @@ Table Create Table
t3 CREATE TABLE `t3` (
`id` int(11) NOT NULL default '0',
`name` char(20) default NULL
-) TYPE=MyISAM CHARSET=latin1
+) TYPE=MyISAM DEFAULT CHARSET=latin1
select * from t3;
id name
drop table t2, t3;
@@ -313,14 +313,14 @@ Table Create Table
t3 CREATE TEMPORARY TABLE `t3` (
`id` int(11) NOT NULL default '0',
`name` char(20) default NULL
-) TYPE=MyISAM CHARSET=latin1
+) TYPE=MyISAM DEFAULT CHARSET=latin1
create table t2 like t3;
show create table t2;
Table Create Table
t2 CREATE TABLE `t2` (
`id` int(11) NOT NULL default '0',
`name` char(20) default NULL
-) TYPE=MyISAM CHARSET=latin1
+) TYPE=MyISAM DEFAULT CHARSET=latin1
select * from t2;
id name
create table t3 like t1;
@@ -346,7 +346,7 @@ show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` int(11) NOT NULL default '0'
-) TYPE=HEAP CHARSET=latin1
+) TYPE=HEAP DEFAULT CHARSET=latin1
drop table t1;
SET SESSION table_type="gemini";
SELECT @@table_type;
@@ -359,7 +359,7 @@ show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` int(11) NOT NULL default '0'
-) TYPE=MyISAM CHARSET=latin1
+) TYPE=MyISAM DEFAULT CHARSET=latin1
SET SESSION table_type=default;
drop table t1;
create table t1(a int,b int,c int unsigned,d date,e char,f datetime,g time,h blob);
diff --git a/mysql-test/r/ctype_collate.result b/mysql-test/r/ctype_collate.result
index 6a9da97042b..2186b155f99 100644
--- a/mysql-test/r/ctype_collate.result
+++ b/mysql-test/r/ctype_collate.result
@@ -491,7 +491,7 @@ SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`latin1_f` char(32) NOT NULL default ''
-) TYPE=MyISAM CHARSET=latin1
+) TYPE=MyISAM DEFAULT CHARSET=latin1
SHOW FIELDS FROM t1;
Field Type Null Key Default Extra
latin1_f char(32)
@@ -501,7 +501,7 @@ SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`latin1_f` char(32) character set latin1 collate latin1_bin default NULL
-) TYPE=MyISAM CHARSET=latin1
+) TYPE=MyISAM DEFAULT CHARSET=latin1
SHOW FIELDS FROM t1;
Field Type Null Key Default Extra
latin1_f char(32) YES NULL
@@ -509,8 +509,8 @@ ALTER TABLE t1 CHARACTER SET latin1 COLLATE latin1_bin;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `latin1_f` char(32) collate latin1_bin default NULL
-) TYPE=MyISAM CHARSET=latin1 COLLATE=latin1_bin
+ `latin1_f` char(32) character set latin1 collate latin1_bin default NULL
+) TYPE=MyISAM DEFAULT CHARSET=latin1
SHOW FIELDS FROM t1;
Field Type Null Key Default Extra
latin1_f char(32) YES NULL
diff --git a/mysql-test/r/ctype_latin1_de.result b/mysql-test/r/ctype_latin1_de.result
index 07ea97258d9..f1049b81d26 100644
--- a/mysql-test/r/ctype_latin1_de.result
+++ b/mysql-test/r/ctype_latin1_de.result
@@ -225,7 +225,7 @@ t1 CREATE TABLE `t1` (
`word` varchar(255) collate latin1_german2_ci NOT NULL default '',
`word2` varchar(255) collate latin1_german2_ci NOT NULL default '',
KEY `word` (`word`)
-) TYPE=MyISAM CHARSET=latin1 COLLATE=latin1_german2_ci
+) TYPE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_german2_ci
insert into t1 (word) values ('ss'),(0xDF),(0xE4),('ae');
update t1 set word2=word;
select word, word=binary 0xdf as t from t1 having t > 0;
@@ -284,7 +284,7 @@ show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`s1` char(5) collate latin1_german2_ci default NULL
-) TYPE=MyISAM CHARSET=latin1 COLLATE=latin1_german2_ci
+) TYPE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_german2_ci
INSERT INTO t1 VALUES ('Ü');
INSERT INTO t1 VALUES ('ue');
SELECT DISTINCT s1 FROM t1;
diff --git a/mysql-test/r/ctype_many.result b/mysql-test/r/ctype_many.result
index c465655473d..764503f9e22 100644
--- a/mysql-test/r/ctype_many.result
+++ b/mysql-test/r/ctype_many.result
@@ -9,14 +9,14 @@ Table Create Table
t1 CREATE TABLE `t1` (
`comment` char(32) character set latin1 NOT NULL default '',
`koi8_ru_f` char(32) character set koi8r NOT NULL default ''
-) TYPE=MyISAM CHARSET=latin5
+) TYPE=MyISAM DEFAULT CHARSET=latin5
ALTER TABLE t1 CHANGE comment comment CHAR(32) CHARACTER SET latin2 NOT NULL;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`comment` char(32) character set latin2 NOT NULL default '',
`koi8_ru_f` char(32) character set koi8r NOT NULL default ''
-) TYPE=MyISAM CHARSET=latin5
+) TYPE=MyISAM DEFAULT CHARSET=latin5
ALTER TABLE t1 ADD latin5_f CHAR(32) NOT NULL;
SHOW CREATE TABLE t1;
Table Create Table
@@ -24,8 +24,8 @@ t1 CREATE TABLE `t1` (
`comment` char(32) character set latin2 NOT NULL default '',
`koi8_ru_f` char(32) character set koi8r NOT NULL default '',
`latin5_f` char(32) NOT NULL default ''
-) TYPE=MyISAM CHARSET=latin5
-ALTER TABLE t1 CHARSET=latin2;
+) TYPE=MyISAM DEFAULT CHARSET=latin5
+ALTER TABLE t1 DEFAULT CHARSET=latin2;
ALTER TABLE t1 ADD latin2_f CHAR(32) NOT NULL;
SHOW CREATE TABLE t1;
Table Create Table
@@ -34,14 +34,14 @@ t1 CREATE TABLE `t1` (
`koi8_ru_f` char(32) character set koi8r NOT NULL default '',
`latin5_f` char(32) character set latin5 NOT NULL default '',
`latin2_f` char(32) NOT NULL default ''
-) TYPE=MyISAM CHARSET=latin2
+) TYPE=MyISAM DEFAULT CHARSET=latin2
ALTER TABLE t1 DROP latin2_f, DROP latin5_f;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`comment` char(32) NOT NULL default '',
`koi8_ru_f` char(32) character set koi8r NOT NULL default ''
-) TYPE=MyISAM CHARSET=latin2
+) TYPE=MyISAM DEFAULT CHARSET=latin2
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('a','LAT SMALL A');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('b','LAT SMALL B');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('c','LAT SMALL C');
diff --git a/mysql-test/r/ctype_mb.result b/mysql-test/r/ctype_mb.result
index ce4a4f98b42..88cd1b4f7fe 100644
--- a/mysql-test/r/ctype_mb.result
+++ b/mysql-test/r/ctype_mb.result
@@ -5,7 +5,7 @@ Table Create Table
t1 CREATE TABLE `t1` (
`c1` char(4) character set utf8 NOT NULL default '',
`c2` char(4) character set utf8 NOT NULL default ''
-) TYPE=MyISAM CHARSET=latin1
+) TYPE=MyISAM DEFAULT CHARSET=latin1
DELETE FROM t1;
ALTER TABLE t1 ADD c3 CHAR(4) CHARACTER SET utf8;
SHOW CREATE TABLE t1;
@@ -14,7 +14,7 @@ t1 CREATE TABLE `t1` (
`c1` char(4) character set utf8 NOT NULL default '',
`c2` char(4) character set utf8 NOT NULL default '',
`c3` char(4) character set utf8 default NULL
-) TYPE=MyISAM CHARSET=latin1
+) TYPE=MyISAM DEFAULT CHARSET=latin1
INSERT INTO t1 VALUES ('aaaabbbbccccdddd','aaaabbbbccccdddd','aaaabbbbccccdddd');
Warnings:
Warning 1264 Data truncated for column 'c1' at row 1
@@ -30,7 +30,7 @@ Table Create Table
t1 CREATE TABLE `t1` (
`a` char(4) character set utf8 default NULL,
KEY `key_a` (`a`(3))
-) TYPE=MyISAM CHARSET=latin1
+) TYPE=MyISAM DEFAULT CHARSET=latin1
SHOW KEYS FROM t1;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
t1 1 key_a 1 a A NULL 9 NULL YES BTREE
@@ -40,7 +40,7 @@ Table Create Table
t1 CREATE TABLE `t1` (
`a` char(4) default NULL,
KEY `key_a` (`a`(3))
-) TYPE=MyISAM CHARSET=latin1
+) TYPE=MyISAM DEFAULT CHARSET=latin1
SHOW KEYS FROM t1;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
t1 1 key_a 1 a A NULL 3 NULL YES BTREE
@@ -50,7 +50,7 @@ Table Create Table
t1 CREATE TABLE `t1` (
`a` char(4) character set utf8 default NULL,
KEY `key_a` (`a`(3))
-) TYPE=MyISAM CHARSET=latin1
+) TYPE=MyISAM DEFAULT CHARSET=latin1
SHOW KEYS FROM t1;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
t1 1 key_a 1 a A NULL 9 NULL YES BTREE
diff --git a/mysql-test/r/ctype_recoding.result b/mysql-test/r/ctype_recoding.result
index 1fe07692290..5afd2c041c8 100644
--- a/mysql-test/r/ctype_recoding.result
+++ b/mysql-test/r/ctype_recoding.result
@@ -6,7 +6,7 @@ SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` char(10) character set cp1251 default NULL
-) TYPE=MyISAM CHARSET=latin1
+) TYPE=MyISAM DEFAULT CHARSET=latin1
SELECT a FROM t1;
a
ÐÒÏÂÁ
@@ -25,7 +25,7 @@ SHOW CREATE TABLE ÔÁÂÌÉÃÁ;
Table Create Table
ÔÁÂÌÉÃÁ CREATE TABLE `ÔÁÂÌÉÃÁ` (
`ÐÏÌÅ` char(32) character set koi8r NOT NULL default '' COMMENT 'ËÏÍÍÅÎÔÁÒÉÊ ÐÏÌÑ'
-) TYPE=MyISAM CHARSET=latin1 COMMENT='ËÏÍÍÅÎÔÁÒÉÊ ÔÁÂÌÉÃÙ'
+) TYPE=MyISAM DEFAULT CHARSET=latin1 COMMENT='ËÏÍÍÅÎÔÁÒÉÊ ÔÁÂÌÉÃÙ'
SHOW FIELDS FROM ÔÁÂÌÉÃÁ;
Field Type Null Key Default Extra
ÐÏÌÅ char(32)
@@ -37,7 +37,7 @@ SHOW CREATE TABLE òàáëèöà;
Table Create Table
òàáëèöà CREATE TABLE `òàáëèöà` (
`ïîëå` char(32) character set koi8r NOT NULL default '' COMMENT 'êîììåíòàðèé ïîëÿ'
-) TYPE=MyISAM CHARSET=latin1 COMMENT='êîììåíòàðèé òàáëèöû'
+) TYPE=MyISAM DEFAULT CHARSET=latin1 COMMENT='êîììåíòàðèé òàáëèöû'
SHOW FIELDS FROM òàáëèöà;
Field Type Null Key Default Extra
ïîëå char(32)
@@ -49,7 +49,7 @@ SHOW CREATE TABLE таблица;
Table Create Table
таблица CREATE TABLE `таблица` (
`поле` char(32) character set koi8r NOT NULL default '' COMMENT 'комментарий полÑ'
-) TYPE=MyISAM CHARSET=latin1 COMMENT='комментарий таблицы'
+) TYPE=MyISAM DEFAULT CHARSET=latin1 COMMENT='комментарий таблицы'
SHOW FIELDS FROM таблица;
Field Type Null Key Default Extra
поле char(32)
diff --git a/mysql-test/r/ctype_ucs.result b/mysql-test/r/ctype_ucs.result
index db626c8acb1..977797f0278 100644
--- a/mysql-test/r/ctype_ucs.result
+++ b/mysql-test/r/ctype_ucs.result
@@ -45,7 +45,7 @@ Table Create Table
t1 CREATE TABLE `t1` (
`l` char(10) character set ucs2 NOT NULL default '',
`r` char(10) character set ucs2 NOT NULL default ''
-) TYPE=MyISAM CHARSET=latin1
+) TYPE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
SET NAMES koi8r;
SET character_set_connection=ucs2;
diff --git a/mysql-test/r/derived.result b/mysql-test/r/derived.result
index 37742893c2b..6d322078018 100644
--- a/mysql-test/r/derived.result
+++ b/mysql-test/r/derived.result
@@ -164,7 +164,7 @@ create table t1 (mat_id MEDIUMINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
create table t2 (mat_id MEDIUMINT UNSIGNED NOT NULL, pla_id MEDIUMINT UNSIGNED NOT NULL);
insert into t1 values (NULL, 'a', 1), (NULL, 'b', 2), (NULL, 'c', 3), (NULL, 'd', 4), (NULL, 'e', 5), (NULL, 'f', 6), (NULL, 'g', 7), (NULL, 'h', 8), (NULL, 'i', 9);
insert into t2 values (1, 100), (1, 101), (1, 102), (2, 100), (2, 103), (2, 104), (3, 101), (3, 102), (3, 105);
-SELECT d.pla_id, m2.mat_id FROM t1 m2 INNER JOIN (SELECT mp.pla_id, MIN(m1.matintnum) AS matintnum FROM t2 mp INNER JOIN t1 m1 ON mp.mat_id=m1.mat_id GROUP BY mp.pla_id) d ON d.matintnum=m2.matintnum;
+SELECT STRAIGHT_JOIN d.pla_id, m2.mat_id FROM t1 m2 INNER JOIN (SELECT mp.pla_id, MIN(m1.matintnum) AS matintnum FROM t2 mp INNER JOIN t1 m1 ON mp.mat_id=m1.mat_id GROUP BY mp.pla_id) d ON d.matintnum=m2.matintnum;
pla_id mat_id
100 1
101 1
@@ -172,7 +172,7 @@ pla_id mat_id
103 2
104 2
105 3
-SELECT d.pla_id, m2.test FROM t1 m2 INNER JOIN (SELECT mp.pla_id, MIN(m1.matintnum) AS matintnum FROM t2 mp INNER JOIN t1 m1 ON mp.mat_id=m1.mat_id GROUP BY mp.pla_id) d ON d.matintnum=m2.matintnum;
+SELECT STRAIGHT_JOIN d.pla_id, m2.test FROM t1 m2 INNER JOIN (SELECT mp.pla_id, MIN(m1.matintnum) AS matintnum FROM t2 mp INNER JOIN t1 m1 ON mp.mat_id=m1.mat_id GROUP BY mp.pla_id) d ON d.matintnum=m2.matintnum;
pla_id test
100 1
101 1
@@ -180,13 +180,13 @@ pla_id test
103 2
104 2
105 3
-explain SELECT d.pla_id, m2.mat_id FROM t1 m2 INNER JOIN (SELECT mp.pla_id, MIN(m1.matintnum) AS matintnum FROM t2 mp INNER JOIN t1 m1 ON mp.mat_id=m1.mat_id GROUP BY mp.pla_id) d ON d.matintnum=m2.matintnum;
+explain SELECT STRAIGHT_JOIN d.pla_id, m2.mat_id FROM t1 m2 INNER JOIN (SELECT mp.pla_id, MIN(m1.matintnum) AS matintnum FROM t2 mp INNER JOIN t1 m1 ON mp.mat_id=m1.mat_id GROUP BY mp.pla_id) d ON d.matintnum=m2.matintnum;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY m2 ALL NULL NULL NULL NULL 9
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 6 Using where
2 DERIVED mp ALL NULL NULL NULL NULL 9 Using temporary; Using filesort
2 DERIVED m2 index NULL PRIMARY 3 NULL 9 Using index
-explain SELECT d.pla_id, m2.test FROM t1 m2 INNER JOIN (SELECT mp.pla_id, MIN(m1.matintnum) AS matintnum FROM t2 mp INNER JOIN t1 m1 ON mp.mat_id=m1.mat_id GROUP BY mp.pla_id) d ON d.matintnum=m2.matintnum;
+explain SELECT STRAIGHT_JOIN d.pla_id, m2.test FROM t1 m2 INNER JOIN (SELECT mp.pla_id, MIN(m1.matintnum) AS matintnum FROM t2 mp INNER JOIN t1 m1 ON mp.mat_id=m1.mat_id GROUP BY mp.pla_id) d ON d.matintnum=m2.matintnum;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY m2 ALL NULL NULL NULL NULL 9
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 6 Using where
diff --git a/mysql-test/r/fulltext.result b/mysql-test/r/fulltext.result
index 56f95ff0c90..f65210bb6f1 100644
--- a/mysql-test/r/fulltext.result
+++ b/mysql-test/r/fulltext.result
@@ -201,7 +201,7 @@ t2 CREATE TABLE `t2` (
`inhalt` text,
KEY `tig` (`ticket`),
FULLTEXT KEY `tix` (`inhalt`)
-) TYPE=MyISAM CHARSET=latin1
+) TYPE=MyISAM DEFAULT CHARSET=latin1
select * from t2 where MATCH inhalt AGAINST (NULL);
ticket inhalt
select * from t2 where MATCH inhalt AGAINST ('foobar');
diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result
index 26741cff864..a3327a7a80b 100644
--- a/mysql-test/r/func_str.result
+++ b/mysql-test/r/func_str.result
@@ -539,7 +539,7 @@ t1 CREATE TABLE `t1` (
`substring(_latin2'ab',1)` char(2) character set latin2 NOT NULL default '',
`insert(_latin2'abcd',2,3,_latin2'ef')` char(6) character set latin2 NOT NULL default '',
`replace(_latin2'abcd',_latin2'b',_latin2'B')` char(4) character set latin2 NOT NULL default ''
-) TYPE=MyISAM CHARSET=latin1
+) TYPE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
select SUBSTR('abcdefg',3,2);
SUBSTR('abcdefg',3,2)
diff --git a/mysql-test/r/func_system.result b/mysql-test/r/func_system.result
index 9d370b43099..d045d4865dc 100644
--- a/mysql-test/r/func_system.result
+++ b/mysql-test/r/func_system.result
@@ -49,7 +49,7 @@ t1 CREATE TABLE `t1` (
`database()` char(34) character set utf8 NOT NULL default '',
`user()` char(77) character set utf8 NOT NULL default '',
`version` char(40) default NULL
-) TYPE=MyISAM CHARSET=latin1
+) TYPE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
select TRUE,FALSE,NULL;
TRUE FALSE NULL
diff --git a/mysql-test/r/gis-rtree.result b/mysql-test/r/gis-rtree.result
index 173a065adc2..ca54ec59938 100644
--- a/mysql-test/r/gis-rtree.result
+++ b/mysql-test/r/gis-rtree.result
@@ -11,7 +11,7 @@ t1 CREATE TABLE `t1` (
`g` geometry NOT NULL default '',
PRIMARY KEY (`fid`),
SPATIAL KEY `g` (`g`(32))
-) TYPE=MyISAM CHARSET=latin1
+) TYPE=MyISAM DEFAULT CHARSET=latin1
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(150 150, 150 150)'));
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(149 149, 151 151)'));
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(148 148, 152 152)'));
@@ -294,7 +294,7 @@ t2 CREATE TABLE `t2` (
`g` geometry NOT NULL default '',
PRIMARY KEY (`fid`),
SPATIAL KEY `g` (`g`(32))
-) TYPE=MyISAM CHARSET=latin1
+) TYPE=MyISAM DEFAULT CHARSET=latin1
SELECT count(*) FROM t2;
count(*)
100
diff --git a/mysql-test/r/innodb.result b/mysql-test/r/innodb.result
index af39dbf51f1..1fd23f1b804 100644
--- a/mysql-test/r/innodb.result
+++ b/mysql-test/r/innodb.result
@@ -819,7 +819,7 @@ Table Create Table
t1 CREATE TABLE `t1` (
`a` char(20) default NULL,
KEY `a` (`a`(5))
-) TYPE=InnoDB CHARSET=latin1
+) TYPE=InnoDB DEFAULT CHARSET=latin1
drop table t1;
create temporary table t1 (a int not null auto_increment, primary key(a)) type=innodb;
insert into t1 values (NULL),(NULL),(NULL);
diff --git a/mysql-test/r/key_cache.result b/mysql-test/r/key_cache.result
index 79fe0599bc4..4bc4cad40a4 100644
--- a/mysql-test/r/key_cache.result
+++ b/mysql-test/r/key_cache.result
@@ -1,3 +1,4 @@
+drop table if exists t1, t2, t3;
SET @save_key_buffer=@@key_buffer_size;
SELECT @@key_buffer_size, @@small.key_buffer_size;
@@key_buffer_size @@small.key_buffer_size
@@ -74,15 +75,15 @@ select @@keycache1.key_buffer_size;
0
select @@keycache1.key_cache_block_size;
@@keycache1.key_cache_block_size
-0
+2048
select @@key_buffer_size;
@@key_buffer_size
2097152
select @@key_cache_block_size;
@@key_cache_block_size
1024
-drop table if exists t1, t2;
-create table t1 (p int primary key, a char(10));
+set global keycache1.key_buffer_size=1024*1024;
+create table t1 (p int primary key, a char(10)) delay_key_write=1;
create table t2 (p int primary key, i int, a char(10), key k1(i), key k2(a));
insert into t1 values (1, 'qqqq'), (11, 'yyyy');
insert into t2 values (1, 1, 'qqqq'), (2, 1, 'pppp'),
@@ -99,7 +100,7 @@ p i a
4 3 zzzz
update t1 set p=2 where p=1;
update t2 set i=2 where i=1;
-cache index t1 keys in keycache1;
+cache index t1 keys (`primary`) in keycache1;
Table Op Msg_type Msg_text
test.t1 assign_to_keycache status OK
explain select p from t1;
@@ -125,15 +126,15 @@ id select_type table type possible_keys key key_len ref rows Extra
select count(*) from t1, t2 where t1.p = t2.i;
count(*)
3
-cache index t2 keys in keycache1;
+cache index t2 in keycache1;
Table Op Msg_type Msg_text
test.t2 assign_to_keycache status OK
update t2 set p=p+1000, i=2 where a='qqqq';
-cache index t2 keys in keycache2;
+cache index t2 in keycache2;
Table Op Msg_type Msg_text
test.t2 assign_to_keycache status OK
insert into t2 values (2000, 3, 'yyyy');
-cache index t2 keys in keycache1;
+cache index t2 in keycache1;
Table Op Msg_type Msg_text
test.t2 assign_to_keycache status OK
update t2 set p=3000 where a='zzzz';
@@ -174,6 +175,12 @@ qqqq
yyyy
yyyy
zzzz
+cache index t1 in unknown_key_cache;
+ERROR HY000: Unknown key cache 'unknown_key_cache'
+cache index t1 keys (unknown_key) in keycache1;
+Table Op Msg_type Msg_text
+test.t1 assign_to_keycache error Key column 'unknown_key' doesn't exist in table
+test.t1 assign_to_keycache status Operation failed
select @@keycache2.key_buffer_size;
@@keycache2.key_buffer_size
4194304
@@ -186,7 +193,11 @@ select @@keycache2.key_buffer_size;
0
select @@keycache2.key_cache_block_size;
@@keycache2.key_cache_block_size
-0
+1024
+set global keycache2.key_buffer_size=1024*1024;
+select @@keycache2.key_buffer_size;
+@@keycache2.key_buffer_size
+1048576
update t2 set p=4000 where a='zzzz';
update t1 set p=p+1;
set global keycache1.key_buffer_size=0;
@@ -232,3 +243,17 @@ select p from t1;
p
3
12
+create table t3 (like t1);
+cache index t3 in small;
+Table Op Msg_type Msg_text
+test.t3 assign_to_keycache status OK
+insert into t3 select * from t1;
+cache index t3 in keycache2;
+Table Op Msg_type Msg_text
+test.t3 assign_to_keycache status OK
+cache index t1,t2 in default;
+Table Op Msg_type Msg_text
+test.t1 assign_to_keycache status OK
+test.t2 assign_to_keycache status OK
+drop table t1,t2,t3;
+set global keycache1.key_buffer_size=0;
diff --git a/mysql-test/r/merge.result b/mysql-test/r/merge.result
index 9a99d1c64fb..01635313590 100644
--- a/mysql-test/r/merge.result
+++ b/mysql-test/r/merge.result
@@ -175,7 +175,7 @@ t3 CREATE TABLE `t3` (
`a` int(11) NOT NULL default '0',
`b` char(20) default NULL,
KEY `a` (`a`)
-) TYPE=MRG_MyISAM CHARSET=latin1 UNION=(`t1`,`t2`)
+) TYPE=MRG_MyISAM DEFAULT CHARSET=latin1 UNION=(`t1`,`t2`)
create table t4 (a int not null, b char(10), key(a)) type=MERGE UNION=(t1,t2);
select * from t4;
ERROR HY000: Can't open file: 't4.MRG' (errno: 143)
@@ -190,7 +190,7 @@ t5 CREATE TABLE `t5` (
`a` int(11) NOT NULL default '0',
`b` char(20) default NULL,
KEY `a` (`a`)
-) TYPE=MRG_MyISAM CHARSET=latin1 UNION=(`t1`,`mysqltest`.`t6`)
+) TYPE=MRG_MyISAM DEFAULT CHARSET=latin1 UNION=(`t1`,`mysqltest`.`t6`)
alter table t5 type=myisam;
drop table t5, mysqltest.t6;
drop database mysqltest;
@@ -263,14 +263,14 @@ t3 CREATE TABLE `t3` (
`incr` int(11) NOT NULL default '0',
`othr` int(11) NOT NULL default '0',
PRIMARY KEY (`incr`)
-) TYPE=MRG_MyISAM CHARSET=latin1 UNION=(`t1`,`t2`)
+) TYPE=MRG_MyISAM DEFAULT CHARSET=latin1 UNION=(`t1`,`t2`)
alter table t3 drop primary key;
show create table t3;
Table Create Table
t3 CREATE TABLE `t3` (
`incr` int(11) NOT NULL default '0',
`othr` int(11) NOT NULL default '0'
-) TYPE=MRG_MyISAM CHARSET=latin1 UNION=(`t1`,`t2`)
+) TYPE=MRG_MyISAM DEFAULT CHARSET=latin1 UNION=(`t1`,`t2`)
drop table t3,t2,t1;
create table t1 (a int not null, key(a)) type=merge;
select * from t1;
@@ -299,28 +299,28 @@ t3 CREATE TABLE `t3` (
`a` int(11) NOT NULL default '0',
`b` int(11) NOT NULL default '0',
KEY `a` (`a`,`b`)
-) TYPE=MyISAM CHARSET=latin1
+) TYPE=MyISAM DEFAULT CHARSET=latin1
show create table t4;
Table Create Table
t4 CREATE TABLE `t4` (
`a` int(11) NOT NULL default '0',
`b` int(11) NOT NULL default '0',
KEY `a` (`a`,`b`)
-) TYPE=MRG_MyISAM CHARSET=latin1 UNION=(`t1`,`t2`)
+) TYPE=MRG_MyISAM DEFAULT CHARSET=latin1 UNION=(`t1`,`t2`)
show create table t5;
Table Create Table
t5 CREATE TABLE `t5` (
`a` int(11) NOT NULL default '0',
`b` int(11) NOT NULL auto_increment,
PRIMARY KEY (`a`,`b`)
-) TYPE=MRG_MyISAM CHARSET=latin1 INSERT_METHOD=FIRST UNION=(`t1`,`t2`)
+) TYPE=MRG_MyISAM DEFAULT CHARSET=latin1 INSERT_METHOD=FIRST UNION=(`t1`,`t2`)
show create table t6;
Table Create Table
t6 CREATE TABLE `t6` (
`a` int(11) NOT NULL default '0',
`b` int(11) NOT NULL auto_increment,
PRIMARY KEY (`a`,`b`)
-) TYPE=MRG_MyISAM CHARSET=latin1 INSERT_METHOD=LAST UNION=(`t1`,`t2`)
+) TYPE=MRG_MyISAM DEFAULT CHARSET=latin1 INSERT_METHOD=LAST UNION=(`t1`,`t2`)
insert into t1 values (1,NULL),(1,NULL),(1,NULL),(1,NULL);
insert into t2 values (2,NULL),(2,NULL),(2,NULL),(2,NULL);
select * from t3 order by b,a limit 3;
@@ -385,7 +385,7 @@ t4 CREATE TABLE `t4` (
`a` int(11) NOT NULL default '0',
`b` int(11) NOT NULL default '0',
KEY `a` (`a`,`b`)
-) TYPE=MRG_MyISAM CHARSET=latin1 UNION=(`t1`,`t2`,`t3`)
+) TYPE=MRG_MyISAM DEFAULT CHARSET=latin1 UNION=(`t1`,`t2`,`t3`)
select * from t4 order by a,b;
a b
1 1
@@ -411,7 +411,7 @@ t4 CREATE TABLE `t4` (
`a` int(11) NOT NULL default '0',
`b` int(11) NOT NULL default '0',
KEY `a` (`a`,`b`)
-) TYPE=MRG_MyISAM CHARSET=latin1 INSERT_METHOD=FIRST UNION=(`t1`,`t2`,`t3`)
+) TYPE=MRG_MyISAM DEFAULT CHARSET=latin1 INSERT_METHOD=FIRST UNION=(`t1`,`t2`,`t3`)
insert into t4 values (4,1),(4,2);
select * from t1 order by a,b;
a b
diff --git a/mysql-test/r/preload.result b/mysql-test/r/preload.result
index 4d9293c7929..bd7b828d5b9 100644
--- a/mysql-test/r/preload.result
+++ b/mysql-test/r/preload.result
@@ -69,7 +69,7 @@ flush status;
select @@preload_buffer_size;
@@preload_buffer_size
32768
-load index into cache t1 keys;
+load index into cache t1;
Table Op Msg_type Msg_text
test.t1 preload_keys status OK
show status like "key_read%";
@@ -93,7 +93,7 @@ set session preload_buffer_size=256*1024;
select @@preload_buffer_size;
@@preload_buffer_size
262144
-load index into cache t1 keys ignore leaves;
+load index into cache t1 ignore leaves;
Table Op Msg_type Msg_text
test.t1 preload_keys status OK
show status like "key_read%";
@@ -117,7 +117,7 @@ set session preload_buffer_size=1*1024;
select @@preload_buffer_size;
@@preload_buffer_size
1024
-load index into cache t1 keys, t2 keys (primary,b) ignore leaves;
+load index into cache t1, t2 keys (primary,b) ignore leaves;
Table Op Msg_type Msg_text
test.t1 preload_keys status OK
test.t2 preload_keys status OK
@@ -141,7 +141,7 @@ show status like "key_read%";
Variable_name Value
Key_read_requests 0
Key_reads 0
-load index into cache t3 keys, t2 keys (primary,b) ;
+load index into cache t3, t2 keys (primary,b) ;
Table Op Msg_type Msg_text
test.t3 preload_keys error Table 'test.t3' doesn't exist
test.t2 preload_keys status OK
diff --git a/mysql-test/r/show_check.result b/mysql-test/r/show_check.result
index 2a5955e6d87..2f29dcfdb47 100644
--- a/mysql-test/r/show_check.result
+++ b/mysql-test/r/show_check.result
@@ -77,13 +77,13 @@ show create table t1;
Table Create Table
t1 CREATE TEMPORARY TABLE `t1` (
`a` int(11) NOT NULL default '0'
-) TYPE=MyISAM CHARSET=latin1
+) TYPE=MyISAM DEFAULT CHARSET=latin1
alter table t1 rename t2;
show create table t2;
Table Create Table
t2 CREATE TEMPORARY TABLE `t2` (
`a` int(11) NOT NULL default '0'
-) TYPE=MyISAM CHARSET=latin1
+) TYPE=MyISAM DEFAULT CHARSET=latin1
drop table t2;
create table t1 (
test_set set( 'val1', 'val2', 'val3' ) not null default '',
@@ -96,7 +96,7 @@ t1 CREATE TABLE `t1` (
`test_set` set('val1','val2','val3') NOT NULL default '',
`name` char(20) default 'O''Brien' COMMENT 'O''Brien as default',
`c` int(11) NOT NULL default '0' COMMENT 'int column'
-) TYPE=MyISAM CHARSET=latin1 COMMENT='it''s a table'
+) TYPE=MyISAM DEFAULT CHARSET=latin1 COMMENT='it''s a table'
show full columns from t1;
Field Type Collation Null Key Default Extra Privileges Comment
test_set set('val1','val2','val3') latin1_swedish_ci select,insert,update,references
@@ -109,7 +109,7 @@ Table Create Table
t1 CREATE TABLE `t1` (
`a` int(11) NOT NULL default '0',
UNIQUE KEY `aa` (`a`)
-) TYPE=MyISAM CHARSET=latin1
+) TYPE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
create table t1 (a int not null, primary key (a));
show create table t1;
@@ -117,7 +117,7 @@ Table Create Table
t1 CREATE TABLE `t1` (
`a` int(11) NOT NULL default '0',
PRIMARY KEY (`a`)
-) TYPE=MyISAM CHARSET=latin1
+) TYPE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
flush tables;
show open tables;
@@ -135,7 +135,7 @@ t1 CREATE TABLE `t1` (
`a` int(11) NOT NULL default '0',
`b` char(10) default NULL,
KEY `b` (`b`)
-) TYPE=MyISAM CHARSET=latin1 MIN_ROWS=10 MAX_ROWS=100 AVG_ROW_LENGTH=10 PACK_KEYS=1 CHECKSUM=1 DELAY_KEY_WRITE=1 ROW_FORMAT=FIXED COMMENT='test'
+) TYPE=MyISAM DEFAULT CHARSET=latin1 MIN_ROWS=10 MAX_ROWS=100 AVG_ROW_LENGTH=10 PACK_KEYS=1 CHECKSUM=1 DELAY_KEY_WRITE=1 ROW_FORMAT=FIXED COMMENT='test'
alter table t1 MAX_ROWS=200 ROW_FORMAT=dynamic PACK_KEYS=0;
show create table t1;
Table Create Table
@@ -143,7 +143,7 @@ t1 CREATE TABLE `t1` (
`a` int(11) NOT NULL default '0',
`b` varchar(10) default NULL,
KEY `b` (`b`)
-) TYPE=MyISAM CHARSET=latin1 MIN_ROWS=10 MAX_ROWS=200 AVG_ROW_LENGTH=10 PACK_KEYS=0 CHECKSUM=1 DELAY_KEY_WRITE=1 ROW_FORMAT=DYNAMIC COMMENT='test'
+) TYPE=MyISAM DEFAULT CHARSET=latin1 MIN_ROWS=10 MAX_ROWS=200 AVG_ROW_LENGTH=10 PACK_KEYS=0 CHECKSUM=1 DELAY_KEY_WRITE=1 ROW_FORMAT=DYNAMIC COMMENT='test'
ALTER TABLE t1 AVG_ROW_LENGTH=0 CHECKSUM=0 COMMENT="" MIN_ROWS=0 MAX_ROWS=0 PACK_KEYS=DEFAULT DELAY_KEY_WRITE=0 ROW_FORMAT=default;
show create table t1;
Table Create Table
@@ -151,7 +151,7 @@ t1 CREATE TABLE `t1` (
`a` int(11) NOT NULL default '0',
`b` varchar(10) default NULL,
KEY `b` (`b`)
-) TYPE=MyISAM CHARSET=latin1
+) TYPE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
create table t1 (a decimal(9,2), b decimal (9,0), e double(9,2), f double(5,0), h float(3,2), i float(3,0));
show columns from t1;
@@ -221,7 +221,7 @@ t1 CREATE TABLE `t1` (
`type_long_blob` longblob,
PRIMARY KEY (`type_tiny`),
KEY `type_short` (`type_short`)
-) TYPE=MyISAM CHARSET=latin1 MIN_ROWS=10 MAX_ROWS=100 AVG_ROW_LENGTH=10 PACK_KEYS=1 CHECKSUM=1 DELAY_KEY_WRITE=1 ROW_FORMAT=FIXED COMMENT='test'
+) TYPE=MyISAM DEFAULT CHARSET=latin1 MIN_ROWS=10 MAX_ROWS=100 AVG_ROW_LENGTH=10 PACK_KEYS=1 CHECKSUM=1 DELAY_KEY_WRITE=1 ROW_FORMAT=FIXED COMMENT='test'
insert into t1 (type_timestamp) values ("2003-02-07 10:00:01");
select * from t1;
type_bool type_tiny type_short type_mediumint type_bigint type_decimal type_numeric empty_char type_char type_varchar type_timestamp type_date type_time type_datetime type_year type_enum type_set type_tinyblob type_blob type_medium_blob type_long_blob
diff --git a/mysql-test/r/sql_mode.result b/mysql-test/r/sql_mode.result
index 06451b8ac34..dddfe2432ee 100644
--- a/mysql-test/r/sql_mode.result
+++ b/mysql-test/r/sql_mode.result
@@ -18,7 +18,7 @@ t1 CREATE TABLE `t1` (
`email` varchar(60) character set latin2 NOT NULL default '',
PRIMARY KEY (`a`),
UNIQUE KEY `email` TYPE BTREE (`email`)
-) TYPE=HEAP CHARSET=latin1 ROW_FORMAT=DYNAMIC
+) TYPE=HEAP DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC
set @@sql_mode="ansi_quotes";
show variables like 'sql_mode';
Variable_name Value
@@ -31,7 +31,7 @@ t1 CREATE TABLE "t1" (
"email" varchar(60) character set latin2 NOT NULL default '',
PRIMARY KEY ("a"),
UNIQUE KEY "email" TYPE BTREE ("email")
-) TYPE=HEAP CHARSET=latin1 ROW_FORMAT=DYNAMIC
+) TYPE=HEAP DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC
set @@sql_mode="no_table_options";
show variables like 'sql_mode';
Variable_name Value
@@ -57,7 +57,7 @@ t1 CREATE TABLE `t1` (
`email` varchar(60) character set latin2 NOT NULL default '',
PRIMARY KEY (`a`),
UNIQUE KEY `email` (`email`)
-) TYPE=HEAP CHARSET=latin1 ROW_FORMAT=DYNAMIC
+) TYPE=HEAP DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC
set @@sql_mode="no_field_options,mysql323,mysql40";
show variables like 'sql_mode';
Variable_name Value
diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result
index 31b5ff84365..95638cbee41 100644
--- a/mysql-test/r/subselect.result
+++ b/mysql-test/r/subselect.result
@@ -1071,7 +1071,7 @@ Table Create Table
t1 CREATE TABLE `t1` (
`a` bigint(1) NOT NULL default '0',
`(SELECT 1)` bigint(1) NOT NULL default '0'
-) TYPE=MyISAM CHARSET=latin1
+) TYPE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
CREATE TABLE t1 SELECT * FROM (SELECT 1 as a,(SELECT a)) a;
SHOW CREATE TABLE t1;
@@ -1079,7 +1079,7 @@ Table Create Table
t1 CREATE TABLE `t1` (
`a` bigint(1) NOT NULL default '0',
`(SELECT a)` bigint(1) NOT NULL default '0'
-) TYPE=MyISAM CHARSET=latin1
+) TYPE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
CREATE TABLE t1 SELECT * FROM (SELECT 1 as a,(SELECT a+0)) a;
SHOW CREATE TABLE t1;
@@ -1087,7 +1087,7 @@ Table Create Table
t1 CREATE TABLE `t1` (
`a` bigint(1) NOT NULL default '0',
`(SELECT a+0)` bigint(17) NOT NULL default '0'
-) TYPE=MyISAM CHARSET=latin1
+) TYPE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
CREATE TABLE t1 SELECT (SELECT 1 as a UNION SELECT 1+1 limit 1,1) as a;
select * from t1;
@@ -1097,7 +1097,7 @@ SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` bigint(17) NOT NULL default '0'
-) TYPE=MyISAM CHARSET=latin1
+) TYPE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
create table t1 (a int);
insert into t1 values (1), (2), (3);
diff --git a/mysql-test/r/type_blob.result b/mysql-test/r/type_blob.result
index 82aefa78bb2..d1147e55119 100644
--- a/mysql-test/r/type_blob.result
+++ b/mysql-test/r/type_blob.result
@@ -23,7 +23,7 @@ Table Create Table
t3 CREATE TABLE `t3` (
`a` mediumtext,
`b` mediumblob
-) TYPE=MyISAM CHARSET=latin1
+) TYPE=MyISAM DEFAULT CHARSET=latin1
drop table t1,t2,t3
#;
CREATE TABLE t1 (a char(257) default "hello");
diff --git a/mysql-test/r/type_enum.result b/mysql-test/r/type_enum.result
index c0f0be246c9..f30feb4c0e6 100644
--- a/mysql-test/r/type_enum.result
+++ b/mysql-test/r/type_enum.result
@@ -1627,12 +1627,12 @@ show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` enum('','a','b') NOT NULL default ''
-) TYPE=MyISAM CHARSET=latin1
+) TYPE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
create table t1 (a enum (' ','a','b ') not null default 'b ');
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` enum('','a','b') NOT NULL default 'b'
-) TYPE=MyISAM CHARSET=latin1
+) TYPE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
diff --git a/mysql-test/r/type_nchar.result b/mysql-test/r/type_nchar.result
index c495853cd4c..63193418f77 100644
--- a/mysql-test/r/type_nchar.result
+++ b/mysql-test/r/type_nchar.result
@@ -4,47 +4,47 @@ show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`c` char(10) character set utf8 default NULL
-) TYPE=MyISAM CHARSET=latin1
+) TYPE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
create table t1 (c national char(10));
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`c` char(10) character set utf8 default NULL
-) TYPE=MyISAM CHARSET=latin1
+) TYPE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
create table t1 (c national varchar(10));
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`c` varchar(10) character set utf8 default NULL
-) TYPE=MyISAM CHARSET=latin1
+) TYPE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
create table t1 (c nvarchar(10));
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`c` varchar(10) character set utf8 default NULL
-) TYPE=MyISAM CHARSET=latin1
+) TYPE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
create table t1 (c nchar varchar(10));
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`c` varchar(10) character set utf8 default NULL
-) TYPE=MyISAM CHARSET=latin1
+) TYPE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
create table t1 (c national character varying(10));
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`c` varchar(10) character set utf8 default NULL
-) TYPE=MyISAM CHARSET=latin1
+) TYPE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
create table t1 (c nchar varying(10));
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`c` varchar(10) character set utf8 default NULL
-) TYPE=MyISAM CHARSET=latin1
+) TYPE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
diff --git a/mysql-test/r/type_set.result b/mysql-test/r/type_set.result
index 086f55a47a5..e98ec2c3fc4 100644
--- a/mysql-test/r/type_set.result
+++ b/mysql-test/r/type_set.result
@@ -4,14 +4,14 @@ show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` set('','a','b') NOT NULL default ''
-) TYPE=MyISAM CHARSET=latin1
+) TYPE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
create table t1 (a set (' ','a','b ') not null default 'b ');
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` set('','a','b') NOT NULL default 'b'
-) TYPE=MyISAM CHARSET=latin1
+) TYPE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
CREATE TABLE t1 ( user varchar(64) NOT NULL default '', path varchar(255) NOT NULL default '', privilege set('select','RESERVED30','RESERVED29','RESERVED28','RESERVED27','RESERVED26', 'RESERVED25','RESERVED24','data.delete','RESERVED22','RESERVED21', 'RESERVED20','data.insert.none','data.insert.approve', 'data.insert.delete','data.insert.move','data.insert.propose', 'data.insert.reject','RESERVED13','RESERVED12','RESERVED11','RESERVED10', 'RESERVED09','data.update','RESERVED07','RESERVED06','RESERVED05', 'RESERVED04','metadata.delete','metadata.put','RESERVED01','RESERVED00') NOT NULL default '', KEY user (user) ) TYPE=MyISAM CHARSET=utf8;
DROP TABLE t1;
diff --git a/mysql-test/r/union.result b/mysql-test/r/union.result
index 5729d3b32ee..00eddd596cf 100644
--- a/mysql-test/r/union.result
+++ b/mysql-test/r/union.result
@@ -486,7 +486,7 @@ a b
2 2
3 3
4 4
-explain (select * from t1 where a=1 and b=10) union (select t1.a,t2.a from t1,t2 where t1.a=t2.a);
+explain (select * from t1 where a=1 and b=10) union (select straight_join t1.a,t2.a from t1,t2 where t1.a=t2.a);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
2 UNION t1 index PRIMARY PRIMARY 4 NULL 4 Using index
diff --git a/mysql-test/t/alter_table.test b/mysql-test/t/alter_table.test
index 06a5db13ea3..11fe997e789 100644
--- a/mysql-test/t/alter_table.test
+++ b/mysql-test/t/alter_table.test
@@ -170,6 +170,17 @@ select a,hex(a) from t1;
alter table t1 change a a char(10) character set koi8r;
select a,hex(a) from t1;
+#
+# Test ALTER TABLE .. CHARACTER SET ..
+#
+show create table t1;
+alter table t1 DEFAULT CHARACTER SET latin1;
+show create table t1;
+alter table t1 CHARACTER SET latin1;
+show create table t1;
+alter table t1 DEFAULT CHARACTER SET cp1251;
+show create table t1;
+
drop table t1;
#
diff --git a/mysql-test/t/ctype_many.test b/mysql-test/t/ctype_many.test
index a1549f952e5..7b44439aa50 100644
--- a/mysql-test/t/ctype_many.test
+++ b/mysql-test/t/ctype_many.test
@@ -16,7 +16,7 @@ ALTER TABLE t1 CHANGE comment comment CHAR(32) CHARACTER SET latin2 NOT NULL;
SHOW CREATE TABLE t1;
ALTER TABLE t1 ADD latin5_f CHAR(32) NOT NULL;
SHOW CREATE TABLE t1;
-ALTER TABLE t1 CHARSET=latin2;
+ALTER TABLE t1 DEFAULT CHARSET=latin2;
ALTER TABLE t1 ADD latin2_f CHAR(32) NOT NULL;
SHOW CREATE TABLE t1;
ALTER TABLE t1 DROP latin2_f, DROP latin5_f;
diff --git a/mysql-test/t/derived.test b/mysql-test/t/derived.test
index 80b131ac6fe..ee50ffda476 100644
--- a/mysql-test/t/derived.test
+++ b/mysql-test/t/derived.test
@@ -83,11 +83,11 @@ create table t2 (mat_id MEDIUMINT UNSIGNED NOT NULL, pla_id MEDIUMINT UNSIGNED N
insert into t1 values (NULL, 'a', 1), (NULL, 'b', 2), (NULL, 'c', 3), (NULL, 'd', 4), (NULL, 'e', 5), (NULL, 'f', 6), (NULL, 'g', 7), (NULL, 'h', 8), (NULL, 'i', 9);
insert into t2 values (1, 100), (1, 101), (1, 102), (2, 100), (2, 103), (2, 104), (3, 101), (3, 102), (3, 105);
-SELECT d.pla_id, m2.mat_id FROM t1 m2 INNER JOIN (SELECT mp.pla_id, MIN(m1.matintnum) AS matintnum FROM t2 mp INNER JOIN t1 m1 ON mp.mat_id=m1.mat_id GROUP BY mp.pla_id) d ON d.matintnum=m2.matintnum;
-SELECT d.pla_id, m2.test FROM t1 m2 INNER JOIN (SELECT mp.pla_id, MIN(m1.matintnum) AS matintnum FROM t2 mp INNER JOIN t1 m1 ON mp.mat_id=m1.mat_id GROUP BY mp.pla_id) d ON d.matintnum=m2.matintnum;
+SELECT STRAIGHT_JOIN d.pla_id, m2.mat_id FROM t1 m2 INNER JOIN (SELECT mp.pla_id, MIN(m1.matintnum) AS matintnum FROM t2 mp INNER JOIN t1 m1 ON mp.mat_id=m1.mat_id GROUP BY mp.pla_id) d ON d.matintnum=m2.matintnum;
+SELECT STRAIGHT_JOIN d.pla_id, m2.test FROM t1 m2 INNER JOIN (SELECT mp.pla_id, MIN(m1.matintnum) AS matintnum FROM t2 mp INNER JOIN t1 m1 ON mp.mat_id=m1.mat_id GROUP BY mp.pla_id) d ON d.matintnum=m2.matintnum;
-explain SELECT d.pla_id, m2.mat_id FROM t1 m2 INNER JOIN (SELECT mp.pla_id, MIN(m1.matintnum) AS matintnum FROM t2 mp INNER JOIN t1 m1 ON mp.mat_id=m1.mat_id GROUP BY mp.pla_id) d ON d.matintnum=m2.matintnum;
-explain SELECT d.pla_id, m2.test FROM t1 m2 INNER JOIN (SELECT mp.pla_id, MIN(m1.matintnum) AS matintnum FROM t2 mp INNER JOIN t1 m1 ON mp.mat_id=m1.mat_id GROUP BY mp.pla_id) d ON d.matintnum=m2.matintnum;
+explain SELECT STRAIGHT_JOIN d.pla_id, m2.mat_id FROM t1 m2 INNER JOIN (SELECT mp.pla_id, MIN(m1.matintnum) AS matintnum FROM t2 mp INNER JOIN t1 m1 ON mp.mat_id=m1.mat_id GROUP BY mp.pla_id) d ON d.matintnum=m2.matintnum;
+explain SELECT STRAIGHT_JOIN d.pla_id, m2.test FROM t1 m2 INNER JOIN (SELECT mp.pla_id, MIN(m1.matintnum) AS matintnum FROM t2 mp INNER JOIN t1 m1 ON mp.mat_id=m1.mat_id GROUP BY mp.pla_id) d ON d.matintnum=m2.matintnum;
drop table t1,t2;
#
diff --git a/mysql-test/t/isam.test b/mysql-test/t/isam.test
index a31ba864b2f..e35ed0dfd4a 100644
--- a/mysql-test/t/isam.test
+++ b/mysql-test/t/isam.test
@@ -12,12 +12,14 @@ create table t1 (a tinyint not null auto_increment, b blob not null, primary key
let $1=100;
disable_query_log;
+--disable_warnings
while ($1)
{
eval insert into t1 (b) values(repeat(char(65+$1),65540-$1));
dec $1;
}
enable_query_log;
+--enable_warnings
delete from t1 where (a & 1);
select sum(length(b)) from t1;
drop table t1;
diff --git a/mysql-test/t/join.test b/mysql-test/t/join.test
index e8977ae9b62..8cef925cc24 100644
--- a/mysql-test/t/join.test
+++ b/mysql-test/t/join.test
@@ -112,7 +112,7 @@ drop table t1, t2;
create table t1 (a int primary key);
insert into t1 values(1),(2);
select t1.a from t1 as t1 left join t1 as t2 using (a) left join t1 as t3 using (a) left join t1 as t4 using (a) left join t1 as t5 using (a) left join t1 as t6 using (a) left join t1 as t7 using (a) left join t1 as t8 using (a) left join t1 as t9 using (a) left join t1 as t10 using (a) left join t1 as t11 using (a) left join t1 as t12 using (a) left join t1 as t13 using (a) left join t1 as t14 using (a) left join t1 as t15 using (a) left join t1 as t16 using (a) left join t1 as t17 using (a) left join t1 as t18 using (a) left join t1 as t19 using (a) left join t1 as t20 using (a) left join t1 as t21 using (a) left join t1 as t22 using (a) left join t1 as t23 using (a) left join t1 as t24 using (a) left join t1 as t25 using (a) left join t1 as t26 using (a) left join t1 as t27 using (a) left join t1 as t28 using (a) left join t1 as t29 using (a) left join t1 as t30 using (a) left join t1 as t31 using (a);
---replace_result "31 tables" "XX tables" "62 tables" "XX tables"
+--replace_result "31 tables" "XX tables" "61 tables" "XX tables"
--error 1116
select t1.a from t1 as t1 left join t1 as t2 using (a) left join t1 as t3 using (a) left join t1 as t4 using (a) left join t1 as t5 using (a) left join t1 as t6 using (a) left join t1 as t7 using (a) left join t1 as t8 using (a) left join t1 as t9 using (a) left join t1 as t10 using (a) left join t1 as t11 using (a) left join t1 as t12 using (a) left join t1 as t13 using (a) left join t1 as t14 using (a) left join t1 as t15 using (a) left join t1 as t16 using (a) left join t1 as t17 using (a) left join t1 as t18 using (a) left join t1 as t19 using (a) left join t1 as t20 using (a) left join t1 as t21 using (a) left join t1 as t22 using (a) left join t1 as t23 using (a) left join t1 as t24 using (a) left join t1 as t25 using (a) left join t1 as t26 using (a) left join t1 as t27 using (a) left join t1 as t28 using (a) left join t1 as t29 using (a) left join t1 as t30 using (a) left join t1 as t31 using (a) left join t1 as t32 using (a) left join t1 as t33 using (a) left join t1 as t34 using (a) left join t1 as t35 using (a) left join t1 as t36 using (a) left join t1 as t37 using (a) left join t1 as t38 using (a) left join t1 as t39 using (a) left join t1 as t40 using (a) left join t1 as t41 using (a) left join t1 as t42 using (a) left join t1 as t43 using (a) left join t1 as t44 using (a) left join t1 as t45 using (a) left join t1 as t46 using (a) left join t1 as t47 using (a) left join t1 as t48 using (a) left join t1 as t49 using (a) left join t1 as t50 using (a) left join t1 as t51 using (a) left join t1 as t52 using (a) left join t1 as t53 using (a) left join t1 as t54 using (a) left join t1 as t55 using (a) left join t1 as t56 using (a) left join t1 as t57 using (a) left join t1 as t58 using (a) left join t1 as t59 using (a) left join t1 as t60 using (a) left join t1 as t61 using (a) left join t1 as t62 using (a) left join t1 as t63 using (a) left join t1 as t64 using (a) left join t1 as t65 using (a);
drop table t1;
diff --git a/mysql-test/t/key_cache.test b/mysql-test/t/key_cache.test
index 371d610eb5f..dc9f9c9b18a 100644
--- a/mysql-test/t/key_cache.test
+++ b/mysql-test/t/key_cache.test
@@ -1,6 +1,9 @@
#
# Test of multiple key caches
#
+--disable_warnings
+drop table if exists t1, t2, t3;
+--enable_warnings
SET @save_key_buffer=@@key_buffer_size;
@@ -58,12 +61,9 @@ select @@keycache1.key_cache_block_size;
select @@key_buffer_size;
select @@key_cache_block_size;
+set global keycache1.key_buffer_size=1024*1024;
---disable_warnings
-drop table if exists t1, t2;
---enable_warnings
-
-create table t1 (p int primary key, a char(10));
+create table t1 (p int primary key, a char(10)) delay_key_write=1;
create table t2 (p int primary key, i int, a char(10), key k1(i), key k2(a));
insert into t1 values (1, 'qqqq'), (11, 'yyyy');
@@ -75,7 +75,7 @@ select * from t2;
update t1 set p=2 where p=1;
update t2 set i=2 where i=1;
-cache index t1 keys in keycache1;
+cache index t1 keys (`primary`) in keycache1;
explain select p from t1;
select p from t1;
@@ -84,11 +84,11 @@ select i from t2;
explain select count(*) from t1, t2 where t1.p = t2.i;
select count(*) from t1, t2 where t1.p = t2.i;
-cache index t2 keys in keycache1;
+cache index t2 in keycache1;
update t2 set p=p+1000, i=2 where a='qqqq';
-cache index t2 keys in keycache2;
+cache index t2 in keycache2;
insert into t2 values (2000, 3, 'yyyy');
-cache index t2 keys in keycache1;
+cache index t2 in keycache1;
update t2 set p=3000 where a='zzzz';
select * from t2;
explain select p from t2;
@@ -98,12 +98,18 @@ select i from t2;
explain select a from t2;
select a from t2;
+# Test some error conditions
+--error 1287
+cache index t1 in unknown_key_cache;
+cache index t1 keys (unknown_key) in keycache1;
+
select @@keycache2.key_buffer_size;
select @@keycache2.key_cache_block_size;
set global keycache2.key_buffer_size=0;
select @@keycache2.key_buffer_size;
select @@keycache2.key_cache_block_size;
-
+set global keycache2.key_buffer_size=1024*1024;
+select @@keycache2.key_buffer_size;
update t2 set p=4000 where a='zzzz';
update t1 set p=p+1;
@@ -119,4 +125,14 @@ select a from t2;
select * from t1;
select p from t1;
+# Use the 'small' key cache
+create table t3 (like t1);
+cache index t3 in small;
+insert into t3 select * from t1;
+cache index t3 in keycache2;
+cache index t1,t2 in default;
+drop table t1,t2,t3;
+# Cleanup
+# We don't reset keycache2 as we want to ensure that mysqld will reset it
+set global keycache1.key_buffer_size=0;
diff --git a/mysql-test/t/preload.test b/mysql-test/t/preload.test
index 7357b42c599..7eff5cee08f 100644
--- a/mysql-test/t/preload.test
+++ b/mysql-test/t/preload.test
@@ -63,7 +63,7 @@ show status like "key_read%";
flush tables; flush status;
select @@preload_buffer_size;
-load index into cache t1 keys;
+load index into cache t1;
show status like "key_read%";
select count(*) from t1 where b = 'test1';
show status like "key_read%";
@@ -72,7 +72,7 @@ flush tables; flush status;
show status like "key_read%";
set session preload_buffer_size=256*1024;
select @@preload_buffer_size;
-load index into cache t1 keys ignore leaves;
+load index into cache t1 ignore leaves;
show status like "key_read%";
select count(*) from t1 where b = 'test1';
show status like "key_read%";
@@ -81,7 +81,7 @@ flush tables; flush status;
show status like "key_read%";
set session preload_buffer_size=1*1024;
select @@preload_buffer_size;
-load index into cache t1 keys, t2 keys (primary,b) ignore leaves;
+load index into cache t1, t2 keys (primary,b) ignore leaves;
show status like "key_read%";
select count(*) from t1 where b = 'test1';
select count(*) from t2 where b = 'test1';
@@ -89,7 +89,7 @@ show status like "key_read%";
flush tables; flush status;
show status like "key_read%";
-load index into cache t3 keys, t2 keys (primary,b) ;
+load index into cache t3, t2 keys (primary,b) ;
show status like "key_read%";
flush tables; flush status;
diff --git a/mysql-test/t/union.test b/mysql-test/t/union.test
index 1f3f4085734..3cfdc14b0b8 100644
--- a/mysql-test/t/union.test
+++ b/mysql-test/t/union.test
@@ -280,7 +280,7 @@ explain extended (select * from t1 where a=1) union (select * from t2 where a=1)
(select * from t1 where a=5 and a=6) union (select * from t2 where a=1);
(select t1.a,t1.b from t1,t2 where t1.a=5) union (select * from t2 where a=1);
(select * from t1 where a=1) union (select t1.a,t2.a from t1,t2 where t1.a=t2.a);
-explain (select * from t1 where a=1 and b=10) union (select t1.a,t2.a from t1,t2 where t1.a=t2.a);
+explain (select * from t1 where a=1 and b=10) union (select straight_join t1.a,t2.a from t1,t2 where t1.a=t2.a);
explain (select * from t1 where a=1) union (select * from t1 where b=1);
drop table t1,t2;
create table t1 ( id int not null auto_increment, primary key (id) ,user_name text );
diff --git a/mysys/Makefile.am b/mysys/Makefile.am
index 37c79e28395..bd508b8de12 100644
--- a/mysys/Makefile.am
+++ b/mysys/Makefile.am
@@ -29,7 +29,7 @@ libmysys_a_SOURCES = my_init.c my_getwd.c mf_getdate.c\
mf_path.c mf_loadpath.c\
my_open.c my_create.c my_dup.c my_seek.c my_read.c \
my_pread.c my_write.c \
- mf_keycache.c my_crc32.c \
+ mf_keycache.c mf_keycaches.c my_crc32.c \
mf_iocache.c mf_iocache2.c mf_cache.c mf_tempfile.c \
mf_tempdir.c my_lock.c mf_brkhant.c my_alarm.c \
my_malloc.c my_realloc.c my_once.c mulalloc.c \
diff --git a/mysys/hash.c b/mysys/hash.c
index b0ddbd90794..516fa171d7c 100644
--- a/mysys/hash.c
+++ b/mysys/hash.c
@@ -53,7 +53,7 @@ _hash_init(HASH *hash,CHARSET_INFO *charset,
if (my_init_dynamic_array_ci(&hash->array,sizeof(HASH_LINK),size,0))
{
hash->free=0; /* Allow call to hash_free */
- DBUG_RETURN(TRUE);
+ DBUG_RETURN(1);
}
hash->key_offset=key_offset;
hash->key_length=key_length;
diff --git a/mysys/mf_keycache.c b/mysys/mf_keycache.c
index 2f5a704234d..280b69b18bf 100644
--- a/mysys/mf_keycache.c
+++ b/mysys/mf_keycache.c
@@ -142,7 +142,7 @@ typedef struct st_block_link
KEY_CACHE_VAR dflt_key_cache_var=
{
- 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
};
KEY_CACHE_HANDLE *dflt_keycache= &dflt_key_cache_var.cache;
@@ -168,7 +168,7 @@ typedef struct st_key_cache
ulong warm_blocks; /* number of blocks in warm sub-chain */
#if defined(KEYCACHE_DEBUG)
long blocks_available; /* number of blocks available in the LRU chain */
-#endif
+#endif
HASH_LINK **hash_root; /* arr. of entries into hash table buckets */
HASH_LINK *hash_link_root; /* memory for hash table links */
HASH_LINK *free_hash_list; /* list of free hash links */
@@ -184,7 +184,7 @@ typedef struct st_key_cache
} KEY_CACHE;
static int flush_all_key_blocks(KEY_CACHE_HANDLE keycache);
-static void test_key_cache(KEY_CACHE *keycache,
+static void test_key_cache(KEY_CACHE *keycache,
const char *where, my_bool lock);
#define KEYCACHE_HASH(f, pos) \
@@ -284,7 +284,7 @@ static uint next_power(uint value)
SYNOPSIS
init_ky_cache()
pkeycache in/out pointer to the key cache handle
- key_cache_block_size size of blocks to keep cached data
+ key_cache_block_size size of blocks to keep cached data
use_mem total memory to use for the key cache
env ref to other parameters of the key cache, if any
@@ -299,7 +299,7 @@ static uint next_power(uint value)
handle for a key cache with new blocks.
It's assumed that no two threads call this function simultaneously
referring to the same key cache handle.
-
+
*/
int init_key_cache(KEY_CACHE_HANDLE *pkeycache, uint key_cache_block_size,
@@ -308,14 +308,14 @@ int init_key_cache(KEY_CACHE_HANDLE *pkeycache, uint key_cache_block_size,
uint blocks, hash_links, length;
int error;
KEY_CACHE *keycache;
-
DBUG_ENTER("init_key_cache");
+ DBUG_ASSERT(key_cache_block_size >= 512);
if (!(keycache= (KEY_CACHE *) *pkeycache) &&
!(keycache= (KEY_CACHE *) my_malloc(sizeof(KEY_CACHE),
MYF(MY_ZEROFILL))))
DBUG_RETURN(0);
-
+
keycache->env= env;
KEYCACHE_DEBUG_OPEN;
@@ -332,30 +332,30 @@ int init_key_cache(KEY_CACHE_HANDLE *pkeycache, uint key_cache_block_size,
if (! keycache->key_cache_inited)
{
- keycache->key_cache_inited= TRUE;
+ keycache->key_cache_inited= 1;
keycache->disk_blocks= -1;
pthread_mutex_init(&keycache->cache_lock, MY_MUTEX_INIT_FAST);
keycache->key_cache_shift= my_bit_log2(key_cache_block_size);
keycache->key_cache_mem_size= use_mem;
keycache->key_cache_block_size= key_cache_block_size;
DBUG_PRINT("info", ("key_cache_block_size: %u",
- key_cache_block_size));
+ key_cache_block_size));
}
-
- /*
- These are safety deallocations: actually we always call the
- function after having called end_key_cache that deallocates
- these memory itself.
- */
+
+ /*
+ These are safety deallocations: actually we always call the
+ function after having called end_key_cache that deallocates
+ these memory itself.
+ */
if (keycache->block_mem)
- my_free_lock((gptr) keycache->block_mem, MYF(0));
+ my_free_lock((gptr) keycache->block_mem, MYF(0));
keycache->block_mem= NULL;
if (keycache->block_root)
- my_free((gptr) keycache->block_root, MYF(0));
+ my_free((gptr) keycache->block_root, MYF(0));
keycache->block_root= NULL;
blocks= (uint) (use_mem / (sizeof(BLOCK_LINK) + 2 * sizeof(HASH_LINK) +
- sizeof(HASH_LINK*) * 5/4 + key_cache_block_size));
+ sizeof(HASH_LINK*) * 5/4 + key_cache_block_size));
/* It doesn't make sense to have too few blocks (less than 8) */
if (blocks >= 8 && keycache->disk_blocks < 0)
{
@@ -371,18 +371,18 @@ int init_key_cache(KEY_CACHE_HANDLE *pkeycache, uint key_cache_block_size,
#endif
while ((length= (ALIGN_SIZE(blocks * sizeof(BLOCK_LINK)) +
ALIGN_SIZE(hash_links * sizeof(HASH_LINK)) +
- ALIGN_SIZE(sizeof(HASH_LINK*) *
+ ALIGN_SIZE(sizeof(HASH_LINK*) *
keycache->hash_entries))) +
((ulong) blocks << keycache->key_cache_shift) > use_mem)
blocks--;
/* Allocate memory for cache page buffers */
- if ((keycache->block_mem=
- my_malloc_lock((ulong) blocks * keycache->key_cache_block_size,
- MYF(0))))
+ if ((keycache->block_mem=
+ my_malloc_lock((ulong) blocks * keycache->key_cache_block_size,
+ MYF(0))))
{
/*
- Allocate memory for blocks, hash_links and hash entries;
- For each block 2 hash links are allocated
+ Allocate memory for blocks, hash_links and hash entries;
+ For each block 2 hash links are allocated
*/
if ((keycache->block_root= (BLOCK_LINK*) my_malloc((uint) length,
MYF(0))))
@@ -402,13 +402,13 @@ int init_key_cache(KEY_CACHE_HANDLE *pkeycache, uint key_cache_block_size,
ALIGN_SIZE(blocks*sizeof(BLOCK_LINK)));
keycache->hash_link_root= (HASH_LINK*) ((char*) keycache->hash_root +
ALIGN_SIZE((sizeof(HASH_LINK*) *
- keycache->hash_entries)));
+ keycache->hash_entries)));
bzero((byte*) keycache->block_root,
- keycache->disk_blocks * sizeof(BLOCK_LINK));
+ keycache->disk_blocks * sizeof(BLOCK_LINK));
bzero((byte*) keycache->hash_root,
keycache->hash_entries * sizeof(HASH_LINK*));
bzero((byte*) keycache->hash_link_root,
- keycache->hash_links * sizeof(HASH_LINK));
+ keycache->hash_links * sizeof(HASH_LINK));
keycache->hash_links_used= 0;
keycache->free_hash_list= NULL;
keycache->blocks_used= keycache->blocks_changed= 0;
@@ -422,21 +422,21 @@ int init_key_cache(KEY_CACHE_HANDLE *pkeycache, uint key_cache_block_size,
keycache->used_ins= NULL;
keycache->keycache_time= 0;
keycache->warm_blocks= 0;
- keycache->min_warm_blocks= env && env->division_limit ?
- blocks * env->division_limit / 100 + 1 :
- blocks;
- keycache->age_threshold= env && env->age_threshold ?
- blocks * env->age_threshold / 100 :
- blocks;
+ keycache->min_warm_blocks= (env && env->division_limit ?
+ blocks * env->division_limit / 100 + 1 :
+ blocks);
+ keycache->age_threshold= (env && env->age_threshold ?
+ blocks * env->age_threshold / 100 :
+ blocks);
keycache->waiting_for_hash_link.last_thread= NULL;
keycache->waiting_for_block.last_thread= NULL;
DBUG_PRINT("exit",
- ("disk_blocks: %d block_root: %lx hash_entries: %d hash_root: %lx \
+ ("disk_blocks: %d block_root: %lx hash_entries: %d hash_root: %lx \
hash_links: %d hash_link_root %lx",
- keycache->disk_blocks, keycache->block_root,
- keycache->hash_entries, keycache->hash_root,
- keycache->hash_links, keycache->hash_link_root));
+ keycache->disk_blocks, keycache->block_root,
+ keycache->hash_entries, keycache->hash_root,
+ keycache->hash_links, keycache->hash_link_root));
}
bzero((gptr) keycache->changed_blocks,
sizeof(keycache->changed_blocks[0]) * CHANGED_BLOCKS_HASH);
@@ -445,7 +445,8 @@ int init_key_cache(KEY_CACHE_HANDLE *pkeycache, uint key_cache_block_size,
if (env)
env->blocks= keycache->disk_blocks > 0 ? keycache->disk_blocks : 0;
- *pkeycache= keycache;
+ *pkeycache= keycache;
+ DBUG_PRINT("exit", ("key_cache: %lx", keycache));
DBUG_RETURN((int) blocks);
err:
@@ -473,8 +474,8 @@ err:
SYNOPSIS
resize_key_cache()
- pkeycache in/out pointer to the key cache handle
- key_cache_block_size size of blocks to keep cached data
+ pkeycache in/out pointer to the key cache handle
+ key_cache_block_size size of blocks to keep cached data
use_mem total memory to use for the new key cache
RETURN VALUE
@@ -485,8 +486,8 @@ err:
The function first compares the memory size and the block size parameters
with the corresponding parameters of the key cache referred by
*pkeycache. If they differ the function free the the memory allocated
- for the old key cache blocks by calling the end_key_cache function
- and then rebuilds the key cache with new blocks by calling init_key_cache.
+ for the old key cache blocks by calling the end_key_cache function
+ and then rebuilds the key cache with new blocks by calling init_key_cache.
*/
int resize_key_cache(KEY_CACHE_HANDLE *pkeycache, uint key_cache_block_size,
@@ -494,6 +495,7 @@ int resize_key_cache(KEY_CACHE_HANDLE *pkeycache, uint key_cache_block_size,
{
int blocks;
KEY_CACHE *keycache= *pkeycache;
+ DBUG_ENTER("resize_key_cache");
if (key_cache_block_size == keycache->key_cache_block_size &&
use_mem == keycache->key_cache_mem_size)
@@ -507,20 +509,20 @@ int resize_key_cache(KEY_CACHE_HANDLE *pkeycache, uint key_cache_block_size,
return 0;
}
keycache_pthread_mutex_unlock(&keycache->cache_lock);
- end_key_cache(pkeycache, 0);
+ end_key_cache(keycache, 0);
/* the following will work even if memory is 0 */
- blocks=init_key_cache(pkeycache, key_cache_block_size, use_mem,
- keycache->env);
+ blocks= init_key_cache(pkeycache, key_cache_block_size, use_mem,
+ keycache->env);
return blocks;
}
/*
- Change the key cache parameters
+ Change the key cache parameters
SYNOPSIS
change_key_cache_param()
- keycache the key cache handle
+ keycache the key cache handle
RETURN VALUE
none
@@ -537,14 +539,15 @@ void change_key_cache_param(KEY_CACHE_HANDLE keycache)
KEY_CACHE_VAR *env= keycache->env;
DBUG_ENTER("change_key_cache_param");
- if (!env)
- return;
- if (env->division_limit)
- keycache->min_warm_blocks= keycache->disk_blocks *
- env->division_limit / 100 + 1;
- if (env->age_threshold)
- keycache->age_threshold= keycache->disk_blocks *
- env->age_threshold / 100;
+ if (env)
+ {
+ if (env->division_limit)
+ keycache->min_warm_blocks= (keycache->disk_blocks *
+ env->division_limit / 100 + 1);
+ if (env->age_threshold)
+ keycache->age_threshold= (keycache->disk_blocks *
+ env->age_threshold / 100);
+ }
DBUG_VOID_RETURN;
}
@@ -554,7 +557,7 @@ void change_key_cache_param(KEY_CACHE_HANDLE keycache)
SYNOPSIS
end_key_cache()
- pkeycache in/out pointer to the key cache handle
+ pkeycache in/out pointer to the key cache handle
cleanup <-> the key cache data structure is freed as well
RETURN VALUE
@@ -562,15 +565,18 @@ void change_key_cache_param(KEY_CACHE_HANDLE keycache)
NOTES.
If the cleanup parameter is TRUE the data structure with all associated
- elements are freed completely and NULL is assigned to *pkeycache.
- Otherwise only memory used by the key cache blocks is freed.
+ elements are freed completely
+ Otherwise only memory used by the key cache blocks is freed.
*/
-void end_key_cache(KEY_CACHE_HANDLE *pkeycache, my_bool cleanup)
+void end_key_cache(KEY_CACHE_HANDLE keycache, my_bool cleanup)
{
- KEY_CACHE *keycache= *pkeycache;
- KEY_CACHE_VAR *env= keycache->env;
+ KEY_CACHE_VAR *env;;
DBUG_ENTER("end_key_cache");
+ DBUG_PRINT("enter", ("key_cache: %lx", keycache));
+
+ if (!keycache)
+ DBUG_VOID_RETURN;
if (keycache->disk_blocks > 0)
{
if (keycache->block_mem)
@@ -584,18 +590,19 @@ void end_key_cache(KEY_CACHE_HANDLE *pkeycache, my_bool cleanup)
}
KEYCACHE_DEBUG_CLOSE;
keycache->key_cache_inited= 0;
- if (env)
+ if ((env= keycache->env))
+ {
DBUG_PRINT("status",
("used: %d changed: %d w_requests: %ld \
writes: %ld r_requests: %ld reads: %ld",
- env->blocks_used, env->blocks_changed,
+ env->blocks_used, env->blocks_changed,
env->cache_w_requests, env->cache_write,
env->cache_r_requests, env->cache_read));
+ }
if (cleanup)
{
pthread_mutex_destroy(&keycache->cache_lock);
- my_free((gptr) *pkeycache, MYF(0));
- *pkeycache= NULL;
+ my_free((gptr) keycache, MYF(0));
}
DBUG_VOID_RETURN;
} /* end_key_cache */
@@ -606,8 +613,8 @@ void end_key_cache(KEY_CACHE_HANDLE *pkeycache, my_bool cleanup)
SYNOPSIS
link_into_queue()
- wqueue pointer to the queue structure
- thread pointer to the thread to be added to the queue
+ wqueue pointer to the queue structure
+ thread pointer to the thread to be added to the queue
RETURN VALUE
none
@@ -643,8 +650,8 @@ static inline void link_into_queue(KEYCACHE_WQUEUE *wqueue,
SYNOPSIS
unlink_from_queue()
- wqueue pointer to the queue structure
- thread pointer to the thread to be removed from the queue
+ wqueue pointer to the queue structure
+ thread pointer to the thread to be removed from the queue
RETURN VALUE
none
@@ -677,8 +684,8 @@ static inline void unlink_from_queue(KEYCACHE_WQUEUE *wqueue,
SYNOPSIS
add_to_queue()
- wqueue pointer to the queue structure
- thread pointer to the thread to be added to the queue
+ wqueue pointer to the queue structure
+ thread pointer to the thread to be added to the queue
RETURN VALUE
none
@@ -709,8 +716,8 @@ static inline void add_to_queue(KEYCACHE_WQUEUE *wqueue,
SYNOPSIS
realease_queue()
- wqueue pointer to the queue structure
- thread pointer to the thread to be added to the queue
+ wqueue pointer to the queue structure
+ thread pointer to the thread to be added to the queue
RETURN VALUE
none
@@ -718,7 +725,7 @@ static inline void add_to_queue(KEYCACHE_WQUEUE *wqueue,
NOTES.
See notes for add_to_queue
When removed from the queue each thread is signaled via condition
- variable thread->suspend.
+ variable thread->suspend.
*/
static void release_queue(KEYCACHE_WQUEUE *wqueue)
@@ -809,7 +816,7 @@ static inline void link_to_changed_list(KEY_CACHE *keycache,
SYNOPSIS
link_block()
- keycache pointer to a key cache data structure
+ keycache pointer to a key cache data structure
block pointer to the block to link to the LRU chain
hot <-> to link the block into the hot subchain
at_end <-> to link the block at the end of the subchain
@@ -818,11 +825,11 @@ static inline void link_to_changed_list(KEY_CACHE *keycache,
none
NOTES.
- The LRU chain is represented by a curcular list of block structures.
- The list is double-linked of the type (**prev,*next) type.
- The LRU chain is divided into two parts - hot and warm.
+ The LRU chain is represented by a curcular list of block structures.
+ The list is double-linked of the type (**prev,*next) type.
+ The LRU chain is divided into two parts - hot and warm.
There are two pointers to access the last blocks of these two
- parts. The beginning of the warm part follows right after the
+ parts. The beginning of the warm part follows right after the
end of the hot part.
Only blocks of the warm part can be used for replacement.
The first block from the beginning of this subchain is always
@@ -836,12 +843,12 @@ static inline void link_to_changed_list(KEY_CACHE *keycache,
| +------+ W A R M +------+ |
+----| beg |---->...----| end |----+
+------+ +------+ins
- first for eviction
+ first for eviction
*/
static void link_block(KEY_CACHE *keycache, BLOCK_LINK *block, my_bool hot,
my_bool at_end)
-{
+{
BLOCK_LINK *ins;
BLOCK_LINK **pins;
@@ -881,7 +888,7 @@ static void link_block(KEY_CACHE *keycache, BLOCK_LINK *block, my_bool hot,
return;
}
pins= hot ? &keycache->used_ins : &keycache->used_last;
- ins= *pins;
+ ins= *pins;
if (ins)
{
ins->next_used->prev_used= &block->next_used;
@@ -915,7 +922,7 @@ static void link_block(KEY_CACHE *keycache, BLOCK_LINK *block, my_bool hot,
SYNOPSIS
unlink_block()
- keycache pointer to a key cache data structure
+ keycache pointer to a key cache data structure
block pointer to the block to unlink from the LRU chain
RETURN VALUE
@@ -938,7 +945,7 @@ static void unlink_block(KEY_CACHE *keycache, BLOCK_LINK *block)
keycache->used_last= STRUCT_PTR(BLOCK_LINK, next_used, block->prev_used);
if (keycache->used_ins == block)
keycache->used_ins=STRUCT_PTR(BLOCK_LINK, next_used, block->prev_used);
- }
+ }
block->next_used= NULL;
KEYCACHE_THREAD_TRACE("unlink_block");
@@ -972,27 +979,27 @@ static void reg_requests(KEY_CACHE *keycache, BLOCK_LINK *block, int count)
SYNOPSIS
unreg_block()
- keycache pointer to a key cache data structure
+ keycache pointer to a key cache data structure
block pointer to the block to link to the LRU chain
at_end <-> to link the block at the end of the LRU chain
RETURN VALUE
none
- NOTES.
+ NOTES.
Every linking to the LRU chain decrements by one a special block
counter (if it's positive). If the at_end parameter is TRUE the block is
added either at the end of warm sub-chain or at the end of hot sub-chain.
- It is added to the hot subchain if its counter is zero and number of
- blocks in warm sub-chain is not less than some low limit (determined by
+ It is added to the hot subchain if its counter is zero and number of
+ blocks in warm sub-chain is not less than some low limit (determined by
the division_limit parameter). Otherwise the block is added to the warm
sub-chain. If the at_end parameter is FALSE the block is always added
- at beginning of the warm sub-chain.
+ at beginning of the warm sub-chain.
Thus a warm block can be promoted to the hot sub-chain when its counter
becomes zero for the first time.
At the same time the block at the very beginning of the hot subchain
might be moved to the beginning of the warm subchain if it stays untouched
- for a too long time (this time is determined by parameter age_threshold).
+ for a too long time (this time is determined by parameter age_threshold).
*/
static inline void unreg_request(KEY_CACHE *keycache,
@@ -1123,7 +1130,7 @@ static void unlink_hash(KEY_CACHE *keycache, HASH_LINK *hash_link)
Get the hash link for a page
*/
-static HASH_LINK *get_hash_link(KEY_CACHE *keycache,
+static HASH_LINK *get_hash_link(KEY_CACHE *keycache,
int file, my_off_t filepos)
{
reg1 HASH_LINK *hash_link, **start;
@@ -1206,16 +1213,16 @@ restart:
Get a block for the file page requested by a keycache read/write operation;
If the page is not in the cache return a free block, if there is none
return the lru block after saving its buffer if the page is dirty.
-
+
SYNOPSIS
find_key_block()
- keycache pointer to a key cache data structure
+ keycache pointer to a key cache data structure
file handler for the file to read page from
filepos position of the page in the file
init_hits_left how initialize the block counter for the page
wrmode <-> get for writing
- page_st out {PAGE_READ,PAGE_TO_BE_READ,PAGE_WAIT_TO_BE_READ}
+ page_st out {PAGE_READ,PAGE_TO_BE_READ,PAGE_WAIT_TO_BE_READ}
RETURN VALUE
Pointer to the found block if successful, 0 - otherwise
@@ -1227,15 +1234,15 @@ restart:
If not, the function first chooses a block for this page. If there is
no not used blocks in the key cache yet, the function takes the block
at the very beginning of the warm sub-chain. It saves the page in that
- block if it's dirty before returning the pointer to it.
+ block if it's dirty before returning the pointer to it.
The function returns in the page_st parameter the following values:
PAGE_READ - if page already in the block,
PAGE_TO_BE_READ - if it is to be read yet by the current thread
- WAIT_TO_BE_READ - if it is to be read by another thread
+ WAIT_TO_BE_READ - if it is to be read by another thread
If an error occurs THE BLOCK_ERROR bit is set in the block status.
It might happen that there are no blocks in LRU chain (in warm part) -
all blocks are unlinked for some read/write operations. Then the function
- waits until first of this operations links any block back.
+ waits until first of this operations links any block back.
*/
static BLOCK_LINK *find_key_block(KEY_CACHE *keycache,
@@ -1388,9 +1395,11 @@ restart:
The call is thread safe because only the current
thread might change the block->hash_link value
*/
- error=my_pwrite(block->hash_link->file, block->buffer,
- block->length, block->hash_link->diskpos,
- MYF(MY_NABP | MY_WAIT_IF_FULL));
+ error= my_pwrite(block->hash_link->file,
+ block->buffer+block->offset,
+ block->length - block->offset,
+ block->hash_link->diskpos+ block->offset,
+ MYF(MY_NABP | MY_WAIT_IF_FULL));
keycache_pthread_mutex_lock(&keycache->cache_lock);
if (keycache->env)
keycache->env->cache_write++;
@@ -1465,12 +1474,12 @@ restart:
SYNOPSIS
read_block()
- keycache pointer to a key cache data structure
+ keycache pointer to a key cache data structure
block block to which buffer the data is to be read
- read_length size of data to be read
- min_length at least so much data must be read
- primary <-> the current thread will read the data
-
+ read_length size of data to be read
+ min_length at least so much data must be read
+ primary <-> the current thread will read the data
+
RETURN VALUE
None
@@ -1551,15 +1560,15 @@ static void read_block(KEY_CACHE *keycache,
SYNOPSIS
key_cache_read()
- keycache pointer to a key cache data structure
+ keycache pointer to a key cache data structure
file handler for the file for the block of data to be read
filepos position of the block of data in the file
level determines the weight of the data
- buff buffer to where the data must be placed
+ buff buffer to where the data must be placed
length length of the buffer
- block_length length of the block in the key cache buffer
- return_buffer return pointer to the key cache buffer with the data
-
+ block_length length of the block in the key cache buffer
+ return_buffer return pointer to the key cache buffer with the data
+
RETURN VALUE
Returns address from where the data is placed if sucessful, 0 - otherwise.
@@ -1584,7 +1593,7 @@ byte *key_cache_read(KEY_CACHE_HANDLE keycache,
DBUG_PRINT("enter", ("file %u, filepos %lu, length %u",
(uint) file, (ulong) filepos, length));
- if (keycache->disk_blocks > 0)
+ if (keycache && keycache->disk_blocks > 0)
{
/* Key cache is used */
reg1 BLOCK_LINK *block;
@@ -1613,7 +1622,7 @@ byte *key_cache_read(KEY_CACHE_HANDLE keycache,
if (block->status != BLOCK_ERROR && page_st != PAGE_READ)
{
/* The requested page is to be read into the block buffer */
- read_block(keycache, block,
+ read_block(keycache, block,
keycache->key_cache_block_size, read_length+offset,
(my_bool)(page_st == PAGE_TO_BE_READ));
}
@@ -1677,7 +1686,7 @@ byte *key_cache_read(KEY_CACHE_HANDLE keycache,
}
/* Key cache is not used */
- if (keycache->env)
+ if (keycache && keycache->env)
{
statistic_increment(keycache->env->cache_r_requests,
&keycache->cache_lock);
@@ -1696,13 +1705,13 @@ byte *key_cache_read(KEY_CACHE_HANDLE keycache,
SYNOPSIS
key_cache_insert()
- keycache pointer to a key cache data structure
+ keycache pointer to a key cache data structure
file handler for the file to insert data from
filepos position of the block of data in the file to insert
level determines the weight of the data
buff buffer to read data from
length length of the data in the buffer
-
+
RETURN VALUE
0 if a success, 1 - otherwise.
*/
@@ -1777,20 +1786,20 @@ int key_cache_insert(KEY_CACHE_HANDLE keycache,
/*
- Write a buffer into a cached file.
-
+ Write a buffer into a cached file.
+
SYNOPSIS
key_cache_write()
- keycache pointer to a key cache data structure
+ keycache pointer to a key cache data structure
file handler for the file to write data to
filepos position in the file to write data to
level determines the weight of the data
- buff buffer with the data
+ buff buffer with the data
length length of the buffer
dont_write if is 0 then all dirty pages involved in writing
- should have been flushed from key cache
-
+ should have been flushed from key cache
+
RETURN VALUE
0 if a success, 1 - otherwise.
@@ -1798,7 +1807,7 @@ int key_cache_insert(KEY_CACHE_HANDLE keycache,
The function copies the data of size length from buff into buffers
for key cache blocks that are assigned to contain the portion of
the file starting with position filepos.
- It ensures that this data is flushed to the file if dont_write is FALSE.
+ It ensures that this data is flushed to the file if dont_write is FALSE.
Filepos must be a multiple of 'block_length', but it doesn't
have to be a multiple of key_cache_block_size;
*/
@@ -1811,15 +1820,16 @@ int key_cache_write(KEY_CACHE_HANDLE keycache,
{
reg1 BLOCK_LINK *block;
int error=0;
-
DBUG_ENTER("key_cache_write");
- DBUG_PRINT("enter", ("file %u, filepos %lu, length %u block_length %u",
- (uint) file, (ulong) filepos, length, block_length));
+ DBUG_PRINT("enter",
+ ("file %u filepos %lu length %u block_length %u key_block_length: %u",
+ (uint) file, (ulong) filepos, length, block_length,
+ keycache ? keycache->key_cache_block_size : 0));
if (!dont_write)
{
/* Force writing from buff into disk */
- if (keycache->env)
+ if (keycache && keycache->env)
statistic_increment(keycache->env->cache_write,
&keycache->cache_lock);
if (my_pwrite(file, buff, length, filepos, MYF(MY_NABP | MY_WAIT_IF_FULL)))
@@ -1831,7 +1841,7 @@ int key_cache_write(KEY_CACHE_HANDLE keycache,
test_key_cache(keycache, "start of key_cache_write", 1););
#endif
- if (keycache->disk_blocks > 0)
+ if (keycache && keycache->disk_blocks > 0)
{
/* Key cache is used */
uint read_length;
@@ -1872,7 +1882,7 @@ int key_cache_write(KEY_CACHE_HANDLE keycache,
if (! (block->status & BLOCK_ERROR))
{
if (!(read_length & 511))
- bmove512(block->buffer+offset, buff, read_length);
+ bmove512(block->buffer+offset, buff, read_length);
else
memcpy(block->buffer+offset, buff, (size_t) read_length);
}
@@ -1903,14 +1913,14 @@ int key_cache_write(KEY_CACHE_HANDLE keycache,
/* Key cache is not used */
if (dont_write)
{
- if (keycache->env)
+ if (keycache && keycache->env)
{
statistic_increment(keycache->env->cache_w_requests,
- &keycache->cache_lock);
- statistic_increment(keycache->env->cache_write,
+ &keycache->cache_lock);
+ statistic_increment(keycache->env->cache_write,
&keycache->cache_lock);
}
- if (my_pwrite(file, (byte*) buff, length, filepos,
+ if (my_pwrite(file, (byte*) buff, length, filepos,
MYF(MY_NABP | MY_WAIT_IF_FULL)))
error=1;
}
@@ -1991,8 +2001,10 @@ static int flush_cached_blocks(KEY_CACHE *keycache,
KEYCACHE_DBUG_PRINT("flush_cached_blocks",
("block %u to be flushed", BLOCK_NUMBER(block)));
keycache_pthread_mutex_unlock(&keycache->cache_lock);
- error= my_pwrite(file, block->buffer+block->offset, block->length,
- block->hash_link->diskpos,
+ error= my_pwrite(file,
+ block->buffer+block->offset,
+ block->length - block->offset,
+ block->hash_link->diskpos+ block->offset,
MYF(MY_NABP | MY_WAIT_IF_FULL));
keycache_pthread_mutex_lock(&keycache->cache_lock);
if (keycache->env)
@@ -2024,27 +2036,30 @@ static int flush_cached_blocks(KEY_CACHE *keycache,
/*
- Flush all blocks for a file to disk
-
- SYNOPSIS
+ flush all key blocks for a file to disk, but don't do any mutex locks
flush_key_blocks()
- keycache pointer to a key cache data structure
+ keycache pointer to a key cache data structure
file handler for the file to flush to
flush_type type of the flush
-
- RETURN VALUE
- 0 if a success, 1 - otherwise.
- */
-int flush_key_blocks(KEY_CACHE_HANDLE keycache,
- File file, enum flush_type type)
+ NOTES
+ This function doesn't do any mutex locks because it needs to be called both
+ from flush_key_blocks and flush_all_key_blocks (the later one does the
+ mutex lock in the resize_key_cache() function).
+
+ RETURN
+ 0 ok
+ 1 error
+*/
+
+static int flush_key_blocks_int(KEY_CACHE_HANDLE keycache,
+ File file, enum flush_type type)
{
KEY_CACHE_VAR *env;
BLOCK_LINK *cache_buff[FLUSH_CACHE],**cache;
int last_errno= 0;
-
- DBUG_ENTER("flush_key_blocks");
+ DBUG_ENTER("flush_key_blocks_int");
DBUG_PRINT("enter",("file: %d blocks_used: %d blocks_changed: %d",
file, keycache->blocks_used, keycache->blocks_changed));
@@ -2053,8 +2068,6 @@ int flush_key_blocks(KEY_CACHE_HANDLE keycache,
test_key_cache(keycache, "start of flush_key_blocks", 0););
#endif
- keycache_pthread_mutex_lock(&keycache->cache_lock);
-
cache= cache_buff;
if (keycache->disk_blocks > 0 &&
(!my_disable_flush_key_blocks || type != FLUSH_KEEP))
@@ -2132,7 +2145,7 @@ restart:
This happens only if there is not enough
memory for the big block
*/
- if ((error= flush_cached_blocks(keycache, file, cache,
+ if ((error= flush_cached_blocks(keycache, file, cache,
end,type)))
last_errno=error;
/*
@@ -2214,12 +2227,8 @@ restart:
}
}
- keycache_pthread_mutex_unlock(&keycache->cache_lock);
-
if (type == FLUSH_REMOVE && (env= keycache->env) && (env->action))
- {
(*env->action)((void *) env);
- }
#ifndef DBUG_OFF
DBUG_EXECUTE("check_keycache",
@@ -2234,6 +2243,37 @@ restart:
/*
+ Flush all blocks for a file to disk
+
+ SYNOPSIS
+
+ flush_key_blocks()
+ keycache pointer to a key cache data structure
+ file handler for the file to flush to
+ flush_type type of the flush
+
+ RETURN
+ 0 ok
+ 1 error
+ */
+
+int flush_key_blocks(KEY_CACHE_HANDLE key_cache,
+ File file, enum flush_type type)
+{
+ int res;
+ DBUG_ENTER("flush_key_blocks");
+ DBUG_PRINT("enter", ("key_cache: %lx", key_cache));
+
+ if (!key_cache || !key_cache->disk_blocks)
+ DBUG_RETURN(0);
+ keycache_pthread_mutex_lock(&key_cache->cache_lock);
+ res= flush_key_blocks_int(key_cache, file, type);
+ keycache_pthread_mutex_unlock(&key_cache->cache_lock);
+ DBUG_RETURN(res);
+}
+
+
+/*
Flush all blocks in the key cache to disk
*/
@@ -2253,7 +2293,8 @@ static int flush_all_key_blocks(KEY_CACHE *keycache)
cnt++;
KEYCACHE_DBUG_ASSERT(cnt <= keycache->blocks_used);
#endif
- if (flush_key_blocks(keycache, block->hash_link->file, FLUSH_RELEASE))
+ if (flush_key_blocks_int(keycache, block->hash_link->file,
+ FLUSH_RELEASE))
return 1;
break;
}
diff --git a/mysys/mf_keycaches.c b/mysys/mf_keycaches.c
new file mode 100644
index 00000000000..1d770e17719
--- /dev/null
+++ b/mysys/mf_keycaches.c
@@ -0,0 +1,359 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+/*
+ Handling of multiple key caches
+
+ The idea is to have a thread safe hash on the table name,
+ with a default key cache value that is returned if the table name is not in
+ the cache.
+*/
+
+#include "mysys_priv.h"
+#include <hash.h>
+#include <m_string.h>
+
+/*****************************************************************************
+ General functions to handle SAFE_HASH objects.
+
+ A SAFE_HASH object is used to store the hash, the mutex and default value
+ needed by the rest of the key cache code.
+ This is a separate struct to make it easy to later reuse the code for other
+ purposes
+
+ All entries are linked in a list to allow us to traverse all elements
+ and delete selected ones. (HASH doesn't allow any easy ways to do this).
+*****************************************************************************/
+
+/*
+ Struct to store a key and pointer to object
+*/
+
+typedef struct st_safe_hash_entry
+{
+ byte *key;
+ uint length;
+ byte *data;
+ struct st_safe_hash_entry *next, **prev;
+} SAFE_HASH_ENTRY;
+
+
+typedef struct st_safe_hash_with_default
+{
+#ifdef THREAD
+ rw_lock_t mutex;
+#endif
+ HASH hash;
+ byte *default_value;
+ SAFE_HASH_ENTRY *root;
+} SAFE_HASH;
+
+
+/*
+ Free a SAFE_HASH_ENTRY
+
+ This function is called by the hash object on delete
+*/
+
+static void safe_hash_entry_free(SAFE_HASH_ENTRY *entry)
+{
+ DBUG_ENTER("free_assign_entry");
+ my_free((gptr) entry, MYF(0));
+ DBUG_VOID_RETURN;
+}
+
+
+/* Get key and length for a SAFE_HASH_ENTRY */
+
+static byte *safe_hash_entry_get(SAFE_HASH_ENTRY *entry, uint *length,
+ my_bool not_used __attribute__((unused)))
+{
+ *length=entry->length;
+ return (byte*) entry->key;
+}
+
+
+/*
+ Init a SAFE_HASH object
+
+ SYNOPSIS
+ safe_hash_init()
+ hash safe_hash handler
+ elements Expected max number of elements
+ default_value default value
+
+ NOTES
+ In case of error we set hash->default_value to 0 to allow one to call
+ safe_hash_free on an object that couldn't be initialized.
+
+ RETURN
+ 0 ok
+ 1 error
+*/
+
+static my_bool safe_hash_init(SAFE_HASH *hash, uint elements,
+ byte *default_value)
+{
+ DBUG_ENTER("safe_hash");
+ if (hash_init(&hash->hash, &my_charset_bin, elements,
+ 0, 0, (hash_get_key) safe_hash_entry_get,
+ (void (*)(void*)) safe_hash_entry_free, 0))
+ {
+ hash->default_value= 0;
+ DBUG_RETURN(1);
+ }
+ my_rwlock_init(&hash->mutex, 0);
+ hash->default_value= default_value;
+ hash->root= 0;
+ DBUG_RETURN(0);
+}
+
+
+/*
+ Free a SAFE_HASH object
+
+ NOTES
+ This is safe to call on any object that has been sent to safe_hash_init()
+*/
+
+static void safe_hash_free(SAFE_HASH *hash)
+{
+ /*
+ Test if safe_hash_init succeeded. This will also guard us against multiple
+ free calls.
+ */
+ if (hash->default_value)
+ {
+ hash_free(&hash->hash);
+ rwlock_destroy(&hash->mutex);
+ hash->default_value=0;
+ }
+}
+
+/*
+ Return the value stored for a key or default value if no key
+*/
+
+static byte *safe_hash_search(SAFE_HASH *hash, const byte *key, uint length)
+{
+ byte *result;
+ DBUG_ENTER("safe_hash_search");
+ rw_rdlock(&hash->mutex);
+ result= hash_search(&hash->hash, key, length);
+ rw_unlock(&hash->mutex);
+ if (!result)
+ result= hash->default_value;
+ else
+ result= ((SAFE_HASH_ENTRY*) result)->data;
+ DBUG_PRINT("exit",("data: %lx", result));
+ DBUG_RETURN(result);
+}
+
+
+/*
+ Associate a key with some data
+
+ SYONOPSIS
+ safe_hash_set()
+ hash Hash handle
+ key key (path to table etc..)
+ length Length of key
+ data data to to associate with the data
+
+ NOTES
+ This can be used both to insert a new entry and change an existing
+ entry.
+ If one associates a key with the default key cache, the key is deleted
+
+ RETURN
+ 0 ok
+ 1 error (Can only be EOM). In this case my_message() is called.
+*/
+
+static my_bool safe_hash_set(SAFE_HASH *hash, const byte *key, uint length,
+ byte *data)
+{
+ SAFE_HASH_ENTRY *entry;
+ my_bool error= 0;
+ DBUG_ENTER("safe_hash_set");
+ DBUG_PRINT("enter",("key: %.*s data: %lx", length, key, data));
+
+ rw_wrlock(&hash->mutex);
+ entry= (SAFE_HASH_ENTRY*) hash_search(&hash->hash, key, length);
+
+ if (data == hash->default_value)
+ {
+ /*
+ The key is to be associated with the default entry. In this case
+ we can just delete the entry (if it existed) from the hash as a
+ search will return the default entry
+ */
+ if (!entry) /* nothing to do */
+ goto end;
+ /* unlink entry from list */
+ if ((*entry->prev= entry->next))
+ entry->next->prev= entry->prev;
+ hash_delete(&hash->hash, (byte*) entry);
+ goto end;
+ }
+ if (entry)
+ {
+ /* Entry existed; Just change the pointer to point at the new data */
+ entry->data= data;
+ }
+ else
+ {
+ if (!(entry= (SAFE_HASH_ENTRY *) my_malloc(sizeof(*entry) + length,
+ MYF(MY_WME))))
+ {
+ error= 1;
+ goto end;
+ }
+ entry->key= (byte*) (entry +1);
+ memcpy((char*) entry->key, (char*) key, length);
+ entry->length= length;
+ entry->data= data;
+ /* Link entry to list */
+ if ((entry->next= hash->root))
+ entry->next->prev= &entry->next;
+ entry->prev= &hash->root;
+ hash->root= entry;
+ if (my_hash_insert(&hash->hash, (byte*) entry))
+ {
+ /* This can only happen if hash got out of memory */
+ my_delete((char*) entry, MYF(0));
+ error= 1;
+ goto end;
+ }
+ }
+
+end:
+ rw_unlock(&hash->mutex);
+ DBUG_RETURN(error);
+}
+
+
+/*
+ Change all entres with one data value to another data value
+
+ SYONOPSIS
+ safe_hash_change()
+ hash Hash handle
+ old_data Old data
+ new_data Change all 'old_data' to this
+
+ NOTES
+ We use the linked list to traverse all elements in the hash as
+ this allows us to delete elements in the case where 'new_data' is the
+ default value.
+*/
+
+static void safe_hash_change(SAFE_HASH *hash, byte *old_data, byte *new_data)
+{
+ SAFE_HASH_ENTRY *entry, *next;
+ DBUG_ENTER("safe_hash_set");
+
+ rw_wrlock(&hash->mutex);
+
+ for (entry= hash->root ; entry ; entry= next)
+ {
+ next= entry->next;
+ if (entry->data == old_data)
+ {
+ if (new_data == hash->default_value)
+ hash_delete(&hash->hash, (byte*) entry);
+ else
+ entry->data= new_data;
+ }
+ }
+
+ rw_unlock(&hash->mutex);
+ DBUG_VOID_RETURN;
+}
+
+
+/*****************************************************************************
+ Functions to handle the key cache objects
+*****************************************************************************/
+
+/* Variable to store all key cache objects */
+static SAFE_HASH key_cache_hash;
+
+
+my_bool multi_keycache_init(void)
+{
+ return safe_hash_init(&key_cache_hash, 16, (byte*) dflt_keycache);
+}
+
+
+void multi_keycache_free(void)
+{
+ safe_hash_free(&key_cache_hash);
+}
+
+/*
+ Get a key cache to be used for a specific table.
+
+ SYNOPSIS
+ multi_key_cache_get()
+ key key to find (usually table path)
+ uint length Length of key.
+
+ NOTES
+ This function is coded in such a way that we will return the
+ default key cache even if one never called multi_keycache_init.
+ This will ensure that it works with old MyISAM clients.
+
+ RETURN
+ key cache to use
+*/
+
+KEY_CACHE_HANDLE *multi_key_cache_search(byte *key, uint length)
+{
+ if (!key_cache_hash.hash.records)
+ return dflt_keycache;
+ return (KEY_CACHE_HANDLE*) safe_hash_search(&key_cache_hash, key, length);
+}
+
+
+/*
+ Assosiate a key cache with a key
+
+
+ SYONOPSIS
+ multi_key_cache_set()
+ key key (path to table etc..)
+ length Length of key
+ key_cache cache to assococite with the table
+
+ NOTES
+ This can be used both to insert a new entry and change an existing
+ entry
+*/
+
+
+my_bool multi_key_cache_set(const byte *key, uint length,
+ KEY_CACHE_HANDLE *key_cache)
+{
+ return safe_hash_set(&key_cache_hash, key, length, (byte*) key_cache);
+}
+
+
+void multi_key_cache_change(KEY_CACHE_HANDLE *old_data,
+ KEY_CACHE_HANDLE *new_data)
+{
+ safe_hash_change(&key_cache_hash, (byte*) old_data, (byte*) new_data);
+}
diff --git a/mysys/my_bitmap.c b/mysys/my_bitmap.c
index aea21fb3d3c..da16457c299 100644
--- a/mysys/my_bitmap.c
+++ b/mysys/my_bitmap.c
@@ -38,6 +38,7 @@
#include <assert.h>
#include <m_string.h>
+
inline void bitmap_lock(MY_BITMAP *map)
{
#ifdef THREAD
@@ -46,6 +47,7 @@ inline void bitmap_lock(MY_BITMAP *map)
#endif
}
+
inline void bitmap_unlock(MY_BITMAP *map)
{
#ifdef THREAD
@@ -54,14 +56,19 @@ inline void bitmap_unlock(MY_BITMAP *map)
#endif
}
-my_bool bitmap_init(MY_BITMAP *map, uchar *buf, uint bitmap_size, my_bool thread_safe)
+
+my_bool bitmap_init(MY_BITMAP *map, uchar *buf, uint bitmap_size,
+ my_bool thread_safe)
{
+ DBUG_ENTER("bitmap_init");
+
DBUG_ASSERT((bitmap_size & 7) == 0);
bitmap_size/=8;
if (!(map->bitmap=buf) &&
- !(map->bitmap=(uchar*)my_malloc(bitmap_size +
- (thread_safe ? sizeof(pthread_mutex_t) : 0),
- MYF(MY_WME | MY_ZEROFILL))))
+ !(map->bitmap= (uchar*) my_malloc(bitmap_size +
+ (thread_safe ?
+ sizeof(pthread_mutex_t) : 0),
+ MYF(MY_WME | MY_ZEROFILL))))
return 1;
map->bitmap_size=bitmap_size;
#ifdef THREAD
@@ -73,22 +80,26 @@ my_bool bitmap_init(MY_BITMAP *map, uchar *buf, uint bitmap_size, my_bool thread
else
map->mutex=0;
#endif
- return 0;
+ DBUG_RETURN(0);
}
+
void bitmap_free(MY_BITMAP *map)
{
-#ifdef THREAD
- if (map->mutex)
- pthread_mutex_destroy(map->mutex);
-#endif
+ DBUG_ENTER("bitmap_free");
if (map->bitmap)
{
+#ifdef THREAD
+ if (map->mutex)
+ pthread_mutex_destroy(map->mutex);
+#endif
my_free((char*) map->bitmap, MYF(0));
map->bitmap=0;
}
+ DBUG_VOID_RETURN;
}
+
void bitmap_set_bit(MY_BITMAP *map, uint bitmap_bit)
{
DBUG_ASSERT(map->bitmap && bitmap_bit < map->bitmap_size*8);
@@ -97,6 +108,7 @@ void bitmap_set_bit(MY_BITMAP *map, uint bitmap_bit)
bitmap_unlock(map);
}
+
uint bitmap_set_next(MY_BITMAP *map)
{
uchar *bitmap=map->bitmap;
@@ -127,6 +139,7 @@ uint bitmap_set_next(MY_BITMAP *map)
return bit_found;
}
+
void bitmap_clear_bit(MY_BITMAP *map, uint bitmap_bit)
{
DBUG_ASSERT(map->bitmap && bitmap_bit < map->bitmap_size*8);
@@ -135,12 +148,13 @@ void bitmap_clear_bit(MY_BITMAP *map, uint bitmap_bit)
bitmap_unlock(map);
}
+
void bitmap_set_prefix(MY_BITMAP *map, uint prefix_size)
{
uint prefix_bytes, prefix_bits;
DBUG_ASSERT(map->bitmap &&
- (prefix_size <= map->bitmap_size*8 || prefix_size == ~0));
+ (prefix_size <= map->bitmap_size*8 || prefix_size == (uint) ~0));
bitmap_lock(map);
set_if_smaller(prefix_size, map->bitmap_size*8);
if ((prefix_bytes= prefix_size / 8))
@@ -152,16 +166,19 @@ void bitmap_set_prefix(MY_BITMAP *map, uint prefix_size)
bitmap_unlock(map);
}
+
void bitmap_clear_all(MY_BITMAP *map)
{
bitmap_set_prefix(map, 0);
}
+
void bitmap_set_all(MY_BITMAP *map)
{
bitmap_set_prefix(map, ~0);
}
+
my_bool bitmap_is_prefix(const MY_BITMAP *map, uint prefix_size)
{
uint prefix_bits= prefix_size & 7, res= 0;
@@ -188,6 +205,7 @@ ret:
return res;
}
+
my_bool bitmap_is_clear_all(const MY_BITMAP *map)
{
return bitmap_is_prefix(map, 0);
@@ -198,15 +216,17 @@ my_bool bitmap_is_set_all(const MY_BITMAP *map)
return bitmap_is_prefix(map, map->bitmap_size*8);
}
+
my_bool bitmap_is_set(const MY_BITMAP *map, uint bitmap_bit)
{
DBUG_ASSERT(map->bitmap && bitmap_bit < map->bitmap_size*8);
return map->bitmap[bitmap_bit / 8] & (1 << (bitmap_bit & 7));
}
+
my_bool bitmap_is_subset(const MY_BITMAP *map1, const MY_BITMAP *map2)
{
- uint length, res=0;
+ uint res=0;
uchar *m1=map1->bitmap, *m2=map2->bitmap, *end;
DBUG_ASSERT(map1->bitmap && map2->bitmap &&
@@ -217,8 +237,10 @@ my_bool bitmap_is_subset(const MY_BITMAP *map1, const MY_BITMAP *map2)
end= m1+map1->bitmap_size;
while (m1 < end)
+ {
if ((*m1++) & ~(*m2++))
goto ret;
+ }
res=1;
ret:
@@ -227,6 +249,7 @@ ret:
return res;
}
+
my_bool bitmap_cmp(const MY_BITMAP *map1, const MY_BITMAP *map2)
{
uint res;
@@ -243,6 +266,7 @@ my_bool bitmap_cmp(const MY_BITMAP *map1, const MY_BITMAP *map2)
return res;
}
+
void bitmap_intersect(MY_BITMAP *map, const MY_BITMAP *map2)
{
uchar *to=map->bitmap, *from=map2->bitmap, *end;
@@ -268,6 +292,7 @@ void bitmap_intersect(MY_BITMAP *map, const MY_BITMAP *map2)
bitmap_unlock(map);
}
+
void bitmap_subtract(MY_BITMAP *map, const MY_BITMAP *map2)
{
uchar *to=map->bitmap, *from=map2->bitmap, *end;
@@ -286,6 +311,7 @@ void bitmap_subtract(MY_BITMAP *map, const MY_BITMAP *map2)
bitmap_unlock(map);
}
+
void bitmap_union(MY_BITMAP *map, const MY_BITMAP *map2)
{
uchar *to=map->bitmap, *from=map2->bitmap, *end;
diff --git a/mysys/my_getopt.c b/mysys/my_getopt.c
index edd35749633..7fa8c9d4fa1 100644
--- a/mysys/my_getopt.c
+++ b/mysys/my_getopt.c
@@ -682,60 +682,77 @@ ulonglong getopt_ull_limit_value(ulonglong num, const struct my_option *optp)
return num;
}
-/*
- function: init_variables
+/*
+ Init one value to it's default values
+
+ SYNOPSIS
+ init_one_value()
+ option Option to initialize
+ value Pointer to variable
+*/
+
+static void init_one_value(const struct my_option *option, gptr *variable,
+ longlong value)
+{
+ switch ((option->var_type & GET_TYPE_MASK)) {
+ case GET_BOOL:
+ *((my_bool*) variable)= (my_bool) value;
+ break;
+ case GET_INT:
+ *((int*) variable)= (int) value;
+ break;
+ case GET_UINT:
+ *((uint*) variable)= (uint) value;
+ break;
+ case GET_LONG:
+ *((long*) variable)= (long) value;
+ break;
+ case GET_ULONG:
+ *((ulong*) variable)= (ulong) value;
+ break;
+ case GET_LL:
+ *((longlong*) variable)= (longlong) value;
+ break;
+ case GET_ULL:
+ *((ulonglong*) variable)= (ulonglong) value;
+ break;
+ default: /* dummy default to avoid compiler warnings */
+ break;
+ }
+}
+
+
+/*
initialize all variables to their default values
+
+ SYNOPSIS
+ init_variables()
+ options Array of options
+
+ NOTES
+ We will initialize the value that is pointed to by options->value.
+ If the value is of type GET_ASK_ADDR, we will also ask for the address
+ for a value and initialize.
*/
static void init_variables(const struct my_option *options)
{
for (; options->name; options++)
{
- gptr *value= (options->var_type & GET_ASK_ADDR ?
- (*getopt_get_addr)("", 0, options) : options->value);
- if (value)
- {
- switch ((options->var_type & GET_TYPE_MASK)) {
- case GET_BOOL:
- if (options->u_max_value)
- *((my_bool*) options->u_max_value)= (my_bool) options->max_value;
- *((my_bool*) value)= (my_bool) options->def_value;
- break;
- case GET_INT:
- if (options->u_max_value)
- *((int*) options->u_max_value)= (int) options->max_value;
- *((int*) value)= (int) options->def_value;
- break;
- case GET_UINT:
- if (options->u_max_value)
- *((uint*) options->u_max_value)= (uint) options->max_value;
- *((uint*) value)= (uint) options->def_value;
- break;
- case GET_LONG:
- if (options->u_max_value)
- *((long*) options->u_max_value)= (long) options->max_value;
- *((long*) value)= (long) options->def_value;
- break;
- case GET_ULONG:
- if (options->u_max_value)
- *((ulong*) options->u_max_value)= (ulong) options->max_value;
- *((ulong*) value)= (ulong) options->def_value;
- break;
- case GET_LL:
- if (options->u_max_value)
- *((longlong*) options->u_max_value)= (longlong) options->max_value;
- *((longlong*) value)= (longlong) options->def_value;
- break;
- case GET_ULL:
- if (options->u_max_value)
- *((ulonglong*) options->u_max_value)= (ulonglong) options->max_value;
- *((ulonglong*) value)= (ulonglong) options->def_value;
- break;
- default: /* dummy default to avoid compiler warnings */
- break;
- }
- }
+ gptr *variable;
+ /*
+ We must set u_max_value first as for some variables
+ options->u_max_value == options->value and in this case we want to
+ set the value to default value.
+ */
+ if (options->u_max_value)
+ init_one_value(options, options->u_max_value, options->max_value);
+ if (options->value)
+ init_one_value(options, options->value, options->def_value);
+ if (options->var_type & GET_ASK_ADDR &&
+ (variable= (*getopt_get_addr)("", 0, options)))
+ init_one_value(options, variable, options->def_value);
}
}
diff --git a/mysys/my_thr_init.c b/mysys/my_thr_init.c
index 9ee7371b639..1d4219e7bfb 100644
--- a/mysys/my_thr_init.c
+++ b/mysys/my_thr_init.c
@@ -28,7 +28,7 @@ pthread_key(struct st_my_thread_var*, THR_KEY_mysys);
#else
pthread_key(struct st_my_thread_var, THR_KEY_mysys);
#endif /* USE_TLS */
-pthread_mutex_t THR_LOCK_malloc,THR_LOCK_open,THR_LOCK_keycache,
+pthread_mutex_t THR_LOCK_malloc,THR_LOCK_open,
THR_LOCK_lock,THR_LOCK_isam,THR_LOCK_myisam,THR_LOCK_heap,
THR_LOCK_net, THR_LOCK_charset;
#if !defined(HAVE_LOCALTIME_R) || !defined(HAVE_GMTIME_R)
@@ -63,7 +63,6 @@ my_bool my_thread_global_init(void)
pthread_mutex_init(&THR_LOCK_malloc,MY_MUTEX_INIT_FAST);
pthread_mutex_init(&THR_LOCK_open,MY_MUTEX_INIT_FAST);
- pthread_mutex_init(&THR_LOCK_keycache,MY_MUTEX_INIT_FAST);
pthread_mutex_init(&THR_LOCK_lock,MY_MUTEX_INIT_FAST);
pthread_mutex_init(&THR_LOCK_isam,MY_MUTEX_INIT_SLOW);
pthread_mutex_init(&THR_LOCK_myisam,MY_MUTEX_INIT_SLOW);
@@ -96,7 +95,6 @@ void my_thread_global_end(void)
#endif
pthread_mutex_destroy(&THR_LOCK_malloc);
pthread_mutex_destroy(&THR_LOCK_open);
- pthread_mutex_destroy(&THR_LOCK_keycache);
pthread_mutex_destroy(&THR_LOCK_lock);
pthread_mutex_destroy(&THR_LOCK_isam);
pthread_mutex_destroy(&THR_LOCK_myisam);
diff --git a/mysys/typelib.c b/mysys/typelib.c
index e32fad8742f..e4eda5bd675 100644
--- a/mysys/typelib.c
+++ b/mysys/typelib.c
@@ -20,15 +20,28 @@
#include <m_string.h>
#include <m_ctype.h>
-/***************************************************************************
-** Search after a fieldtype. Endspace in x is not compared.
-** If part, uniq field is found and full_name == 0 then x is expanded
-** to full field.
-** full_name has the following bit values:
-** If & 1 accept only whole names
-** If & 2 don't expand if half field
-** If & 4 allow #number# as type
-****************************************************************************/
+
+/*
+ Search after a string in a list of strings. Endspace in x is not compared.
+
+ SYNOPSIS
+ find_type()
+ x String to find
+ lib TYPELIB (struct of pointer to values + count)
+ full_name bitmap of what to do
+ If & 1 accept only whole names
+ If & 2 don't expand if half field
+ If & 4 allow #number# as type
+
+ NOTES
+ If part, uniq field is found and full_name == 0 then x is expanded
+ to full field.
+
+ RETURN
+ -1 Too many matching values
+ 0 No matching value
+ >0 Offset+1 in typelib for matched string
+*/
int find_type(my_string x, TYPELIB *typelib, uint full_name)
{
diff --git a/sql-common/client.c b/sql-common/client.c
index 85308539222..c6abfb0ba91 100644
--- a/sql-common/client.c
+++ b/sql-common/client.c
@@ -754,7 +754,15 @@ mysql_free_result(MYSQL_RES *result)
if ((pkt_len=net_safe_read(result->handle)) == packet_error)
break;
if (pkt_len <= 8 && result->handle->net.read_pos[0] == 254)
+ {
+ if (protocol_41(result->handle))
+ {
+ char *pos= (char*) result->handle->net.read_pos;
+ result->handle->warning_count=uint2korr(pos); pos+=2;
+ result->handle->server_status=uint2korr(pos); pos+=2;
+ }
break; /* End of data */
+ }
}
result->handle->status=MYSQL_STATUS_READY;
}
@@ -987,7 +995,7 @@ void mysql_read_default_options(struct st_mysql_options *options,
options->client_flag|= CLIENT_MULTI_RESULTS;
break;
case 31:
- options->client_flag|= CLIENT_MULTI_QUERIES | CLIENT_MULTI_RESULTS;
+ options->client_flag|= CLIENT_MULTI_STATEMENTS | CLIENT_MULTI_RESULTS;
break;
default:
DBUG_PRINT("warning",("unknown option: %s",option[0]));
@@ -1231,6 +1239,7 @@ MYSQL_DATA * STDCALL cli_read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields,
if (pkt_len > 1) /* MySQL 4.1 protocol */
{
mysql->warning_count= uint2korr(cp+1);
+ mysql->server_status= uint2korr(cp+3);
DBUG_PRINT("info",("warning_count: %ld", mysql->warning_count));
}
DBUG_PRINT("exit",("Got %d rows",result->rows));
@@ -1256,7 +1265,10 @@ read_one_row(MYSQL *mysql,uint fields,MYSQL_ROW row, ulong *lengths)
if (pkt_len <= 8 && net->read_pos[0] == 254)
{
if (pkt_len > 1) /* MySQL 4.1 protocol */
+ {
mysql->warning_count= uint2korr(net->read_pos+1);
+ mysql->server_status= uint2korr(net->read_pos+3);
+ }
return 1; /* End of data */
}
prev_pos= 0; /* allowed to write at packet[-1] */
@@ -1818,7 +1830,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
client_flag|=mysql->options.client_flag;
client_flag|=CLIENT_CAPABILITIES;
- if (client_flag & CLIENT_MULTI_QUERIES)
+ if (client_flag & CLIENT_MULTI_STATEMENTS)
client_flag|= CLIENT_MULTI_RESULTS;
#ifdef HAVE_OPENSSL
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 3ed0396e373..f8b5efc93e2 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -2652,6 +2652,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;
@@ -2689,7 +2691,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 12c772e7253..848689282bb 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 7c432a05786..79b5c2fc546 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 8d64a684476..0bcdffdbda4 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;
@@ -1772,24 +1777,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)
{
@@ -1799,115 +1801,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;
}
@@ -2507,13 +2528,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;
@@ -2525,60 +2547,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 c01df3b53cd..6cb8b7110ae 100644
--- a/sql/share/czech/errmsg.txt
+++ b/sql/share/czech/errmsg.txt
@@ -299,3 +299,4 @@ character-set=latin2
"catalog",
"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 e67c430c4f7..e9a02d77bc1 100644
--- a/sql/share/danish/errmsg.txt
+++ b/sql/share/danish/errmsg.txt
@@ -293,3 +293,4 @@ character-set=latin1
"catalog",
"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 5f77163eeda..3356babc74e 100644
--- a/sql/share/dutch/errmsg.txt
+++ b/sql/share/dutch/errmsg.txt
@@ -301,3 +301,4 @@ character-set=latin1
"catalog",
"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 baecefb8494..922457720fd 100644
--- a/sql/share/english/errmsg.txt
+++ b/sql/share/english/errmsg.txt
@@ -290,3 +290,4 @@ character-set=latin1
"catalog",
"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 09e63ddd804..043f95f5f59 100644
--- a/sql/share/estonian/errmsg.txt
+++ b/sql/share/estonian/errmsg.txt
@@ -295,3 +295,4 @@ character-set=latin7
"catalog",
"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 0956db6681e..ae22ab1039d 100644
--- a/sql/share/french/errmsg.txt
+++ b/sql/share/french/errmsg.txt
@@ -290,3 +290,4 @@ character-set=latin1
"catalog",
"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 2cc98971915..8f963a396b8 100644
--- a/sql/share/german/errmsg.txt
+++ b/sql/share/german/errmsg.txt
@@ -302,3 +302,4 @@ character-set=latin1
"catalog",
"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 84e48d2f284..6aa706693c2 100644
--- a/sql/share/greek/errmsg.txt
+++ b/sql/share/greek/errmsg.txt
@@ -290,3 +290,4 @@ character-set=greek
"catalog",
"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 da71f4b7da6..63f3fe79e92 100644
--- a/sql/share/hungarian/errmsg.txt
+++ b/sql/share/hungarian/errmsg.txt
@@ -292,3 +292,4 @@ character-set=latin2
"catalog",
"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 4ed4d477ab8..a8fc6d24fb9 100644
--- a/sql/share/italian/errmsg.txt
+++ b/sql/share/italian/errmsg.txt
@@ -290,3 +290,4 @@ character-set=latin1
"catalog",
"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 d28cc026159..30f8e12ecd4 100644
--- a/sql/share/japanese/errmsg.txt
+++ b/sql/share/japanese/errmsg.txt
@@ -292,3 +292,4 @@ character-set=ujis
"catalog",
"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 b0c4bf9463e..5270cf5d322 100644
--- a/sql/share/korean/errmsg.txt
+++ b/sql/share/korean/errmsg.txt
@@ -290,3 +290,4 @@ character-set=euckr
"catalog",
"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 1e9028de1d7..db66990323d 100644
--- a/sql/share/norwegian-ny/errmsg.txt
+++ b/sql/share/norwegian-ny/errmsg.txt
@@ -292,3 +292,4 @@ character-set=latin1
"catalog",
"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 942c18cc045..248851a618f 100644
--- a/sql/share/norwegian/errmsg.txt
+++ b/sql/share/norwegian/errmsg.txt
@@ -292,3 +292,4 @@ character-set=latin1
"catalog",
"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 17e6df6c443..7f4ead60986 100644
--- a/sql/share/polish/errmsg.txt
+++ b/sql/share/polish/errmsg.txt
@@ -294,3 +294,4 @@ character-set=latin2
"catalog",
"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 fdf428c9b6d..34a773b3eb8 100644
--- a/sql/share/portuguese/errmsg.txt
+++ b/sql/share/portuguese/errmsg.txt
@@ -291,3 +291,4 @@ character-set=latin1
"catalog",
"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 8f4fdb3a702..64befc4f554 100644
--- a/sql/share/romanian/errmsg.txt
+++ b/sql/share/romanian/errmsg.txt
@@ -294,3 +294,4 @@ character-set=latin2
"catalog",
"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 2ef6a2c553b..6e807e07638 100644
--- a/sql/share/russian/errmsg.txt
+++ b/sql/share/russian/errmsg.txt
@@ -292,3 +292,4 @@ character-set=koi8r
"catalog",
"ëÅÛ ÚÁÐÒÏÓÏ× ÎÅ ÍÏÖÅÔ ÕÓÔÁÎÏ×ÉÔØ ÒÁÚÍÅÒ %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 cddc1059f44..aed483fffec 100644
--- a/sql/share/serbian/errmsg.txt
+++ b/sql/share/serbian/errmsg.txt
@@ -285,3 +285,4 @@ character-set=cp1250
"catalog",
"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 466e7d478b6..44faa117a85 100644
--- a/sql/share/slovak/errmsg.txt
+++ b/sql/share/slovak/errmsg.txt
@@ -298,3 +298,4 @@ character-set=latin2
"catalog",
"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 de8a245c7f9..071a204687b 100644
--- a/sql/share/spanish/errmsg.txt
+++ b/sql/share/spanish/errmsg.txt
@@ -292,3 +292,4 @@ character-set=latin1
"catalog",
"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 d8695db30a4..714f2be0e07 100644
--- a/sql/share/swedish/errmsg.txt
+++ b/sql/share/swedish/errmsg.txt
@@ -290,3 +290,4 @@ character-set=latin1
"katalog",
"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 3a37ee02731..60692bb7c02 100644
--- a/sql/share/ukrainian/errmsg.txt
+++ b/sql/share/ukrainian/errmsg.txt
@@ -295,3 +295,4 @@ character-set=koi8u
"catalog",
"ëÅÛ ÚÁÐÉÔ¦× ÎÅÓÐÒÏÍÏÖÅÎ ×ÓÔÁÎÏ×ÉÔÉ ÒÏÚÍ¦Ò %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 b7d6c642398..05973389eac 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 b3c17167a3a..38633080244 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))
@@ -1966,7 +1990,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:
@@ -2108,6 +2132,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;
@@ -2409,7 +2446,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,
@@ -4620,15 +4657,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 d2d1926ea06..0f7fb7029aa 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 */