1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-27 18:02:13 +03:00

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.
This commit is contained in:
monty@mashka.mysql.fi
2003-11-18 13:47:27 +02:00
parent f277c9f88a
commit cab1dc628c
125 changed files with 1754 additions and 1216 deletions

View File

@ -8,7 +8,8 @@ c_warnings="$c_warnings $debug_extra_warnings"
cxx_warnings="$cxx_warnings $debug_extra_warnings" cxx_warnings="$cxx_warnings $debug_extra_warnings"
extra_configs="$pentium_configs $debug_configs" 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" . "$path/FINISH.sh"

View File

@ -2571,7 +2571,7 @@ sql_real_connect(char *host,char *database,char *user,char *password,
mysql_options(&mysql, MYSQL_SET_CHARSET_NAME, default_charset); mysql_options(&mysql, MYSQL_SET_CHARSET_NAME, default_charset);
if (!mysql_real_connect(&mysql, host, user, password, if (!mysql_real_connect(&mysql, host, user, password,
database, opt_mysql_port, opt_mysql_unix_port, database, opt_mysql_port, opt_mysql_unix_port,
connect_flag | CLIENT_MULTI_QUERIES)) connect_flag | CLIENT_MULTI_STATEMENTS))
{ {
if (!silent || if (!silent ||
(mysql_errno(&mysql) != CR_CONN_HOST_ERROR && (mysql_errno(&mysql) != CR_CONN_HOST_ERROR &&

View File

@ -126,14 +126,14 @@ enum ha_extra_function {
HA_EXTRA_RESET_STATE, /* Reset positions */ HA_EXTRA_RESET_STATE, /* Reset positions */
HA_EXTRA_IGNORE_DUP_KEY, /* Dup keys don't rollback everything*/ HA_EXTRA_IGNORE_DUP_KEY, /* Dup keys don't rollback everything*/
HA_EXTRA_NO_IGNORE_DUP_KEY, HA_EXTRA_NO_IGNORE_DUP_KEY,
HA_EXTRA_RETRIEVE_ALL_COLS, /* Instructs InnoDB to retrieve all /*
columns, not just those where Instructs InnoDB to retrieve all columns, not just those where
field->query_id is the same as the field->query_id is the same as the current query id
current query id */ */
HA_EXTRA_RETRIEVE_ALL_COLS,
HA_EXTRA_PREPARE_FOR_DELETE, HA_EXTRA_PREPARE_FOR_DELETE,
HA_EXTRA_PREPARE_FOR_UPDATE, /* Remove read cache if problems */ HA_EXTRA_PREPARE_FOR_UPDATE, /* Remove read cache if problems */
HA_EXTRA_PRELOAD_BUFFER_SIZE, /* Set buffer size for preloading */ 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() */ /* The following is parameter to ha_panic() */

View File

@ -27,5 +27,9 @@
#define pthread_mutex_lock(A) #define pthread_mutex_lock(A)
#define pthread_mutex_unlock(A) #define pthread_mutex_unlock(A)
#define pthread_mutex_destroy(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 #endif

View File

@ -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 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 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_FOR_USER_TO_FIX_PANIC 60 /* in seconds */
#define MY_WAIT_GIVE_USER_A_MESSAGE 10 /* Every 10 times of prev */ #define MY_WAIT_GIVE_USER_A_MESSAGE 10 /* Every 10 times of prev */
#define MIN_COMPRESS_LENGTH 50 /* Don't compress small bl. */ #define MIN_COMPRESS_LENGTH 50 /* Don't compress small bl. */
#define DFLT_INIT_HITS 3
/* root_alloc flags */ /* root_alloc flags */
#define MY_KEEP_PREALLOC 1 #define MY_KEEP_PREALLOC 1
@ -510,13 +511,13 @@ typedef struct st_key_cache* KEY_CACHE_HANDLE;
/* Key cache variable structure */ /* Key cache variable structure */
/* /*
The structure contains the parameters of a key cache that can The structure contains the parameters of a key cache that can
be set and undated by regular set global statements. be set and undated by regular set global statements.
It also contains read-only statistics parameters. It also contains read-only statistics parameters.
If the corresponding key cache data structure has been already If the corresponding key cache data structure has been already
created the variable contains the key cache handle. created the variable contains the key cache handle.
The variables are put into a named list called key_caches. The variables are put into a named list called key_caches.
At present the variables are only added to this list. At present the variables are only added to this list.
*/ */
typedef struct st_key_cache_var 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_r_requests; /* number of read requests (read hits) */
ulong cache_read; /* number of reads from files to the cache */ ulong cache_read; /* number of reads from files to the cache */
int blocks; /* max number of blocks in 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 */ struct st_key_cache_asmt *assign_list; /* list of assignments to the cache */
int assignments; /* number of not completed assignments */ int assignments; /* number of not completed assignments */
void (*action)(void *); /* optional call back function */ void (*action)(void *); /* optional call back function */
void *extra_info; /* ptr to extra info */ void *extra_info; /* ptr to extra info */
} KEY_CACHE_VAR; } KEY_CACHE_VAR;
#define DEFAULT_KEY_CACHE_NAME "default"
extern KEY_CACHE_HANDLE *dflt_keycache; extern KEY_CACHE_HANDLE *dflt_keycache;
extern KEY_CACHE_VAR dflt_key_cache_var; extern KEY_CACHE_VAR dflt_key_cache_var;
#define DFLT_INIT_HITS 3
#include <my_alloc.h> #include <my_alloc.h>
@ -701,7 +702,15 @@ extern int key_cache_write(KEY_CACHE_HANDLE keycache,
uint block_length,int force_write); uint block_length,int force_write);
extern int flush_key_blocks(KEY_CACHE_HANDLE keycache, extern int flush_key_blocks(KEY_CACHE_HANDLE keycache,
int file, enum flush_type type); 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 sig_handler my_set_alarm_variable(int signo);
extern void my_string_ptr_sort(void *base,uint items,size_s size); 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, extern void radixsort_for_str_ptr(uchar* base[], uint number_of_elements,

View File

@ -324,7 +324,7 @@ typedef struct st_mi_check_param
sort_buffer_length,sort_key_blocks; sort_buffer_length,sort_key_blocks;
uint out_flag,warning_printed,error_printed,verbose; uint out_flag,warning_printed,error_printed,verbose;
uint opt_sort_key,total_files,max_level; uint opt_sort_key,total_files,max_level;
uint testflag; uint testflag, key_cache_block_size;
uint8 language; uint8 language;
my_bool using_global_keycache, opt_lock_memory, opt_follow_links; my_bool using_global_keycache, opt_lock_memory, opt_follow_links;
my_bool retry_repair, force_sort, calc_checksum; 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, int lock_file(MI_CHECK *param, File file, my_off_t start, int lock_type,
const char *filetype, const char *filename); const char *filetype, const char *filename);
void lock_memory(MI_CHECK *param); 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, void update_auto_increment_key(MI_CHECK *param, MI_INFO *info,
my_bool repair); my_bool repair);
int update_state_info(MI_CHECK *param, MI_INFO *info,uint update); 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); 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_flush_bulk_insert(MI_INFO *info, uint inx);
void mi_end_bulk_insert(MI_INFO *info); void mi_end_bulk_insert(MI_INFO *info);
int mi_assign_to_keycache(MI_INFO *info, ulonglong key_map, int mi_assign_to_key_cache(MI_INFO *info, ulonglong key_map,
KEY_CACHE_VAR *key_cache, KEY_CACHE_VAR *key_cache);
pthread_mutex_t *assign_lock); 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); int mi_preload(MI_INFO *info, ulonglong key_map, my_bool ignore_leaves);
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -411,6 +411,9 @@ int STDCALL mysql_dump_debug_info(MYSQL *mysql);
int STDCALL mysql_refresh(MYSQL *mysql, int STDCALL mysql_refresh(MYSQL *mysql,
unsigned int refresh_options); unsigned int refresh_options);
int STDCALL mysql_kill(MYSQL *mysql,unsigned long pid); 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); int STDCALL mysql_ping(MYSQL *mysql);
const char * STDCALL mysql_stat(MYSQL *mysql); const char * STDCALL mysql_stat(MYSQL *mysql);
const char * STDCALL mysql_get_server_info(MYSQL *mysql); const char * STDCALL mysql_get_server_info(MYSQL *mysql);

View File

@ -44,7 +44,7 @@ enum enum_server_command
COM_TIME, COM_DELAYED_INSERT, COM_CHANGE_USER, COM_BINLOG_DUMP, COM_TIME, COM_DELAYED_INSERT, COM_CHANGE_USER, COM_BINLOG_DUMP,
COM_TABLE_DUMP, COM_CONNECT_OUT, COM_REGISTER_SLAVE, COM_TABLE_DUMP, COM_CONNECT_OUT, COM_REGISTER_SLAVE,
COM_PREPARE, COM_EXECUTE, COM_LONG_DATA, COM_CLOSE_STMT, COM_PREPARE, COM_EXECUTE, COM_LONG_DATA, COM_CLOSE_STMT,
COM_RESET_STMT, COM_RESET_STMT, COM_SET_OPTION,
COM_END /* Must be last */ COM_END /* Must be last */
}; };
@ -116,7 +116,7 @@ enum enum_server_command
#define CLIENT_TRANSACTIONS 8192 /* Client knows about transactions */ #define CLIENT_TRANSACTIONS 8192 /* Client knows about transactions */
#define CLIENT_RESERVED 16384 /* Old flag for 4.1 protocol */ #define CLIENT_RESERVED 16384 /* Old flag for 4.1 protocol */
#define CLIENT_SECURE_CONNECTION 32768 /* New 4.1 authentication */ #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_MULTI_RESULTS 131072 /* Enable/disable multi-results */
#define CLIENT_REMEMBER_OPTIONS (1L << 31) #define CLIENT_REMEMBER_OPTIONS (1L << 31)
@ -192,6 +192,7 @@ enum enum_field_types { MYSQL_TYPE_DECIMAL, MYSQL_TYPE_TINY,
}; };
/* For backward compatibility */ /* For backward compatibility */
#define CLIENT_MULTI_QUERIES CLIENT_MULTI_STATEMENTS
#define FIELD_TYPE_DECIMAL MYSQL_TYPE_DECIMAL #define FIELD_TYPE_DECIMAL MYSQL_TYPE_DECIMAL
#define FIELD_TYPE_TINY MYSQL_TYPE_TINY #define FIELD_TYPE_TINY MYSQL_TYPE_TINY
#define FIELD_TYPE_SHORT MYSQL_TYPE_SHORT #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 #define MYSQL_TYPE_UINT24 -4
#endif #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) #define net_new_transaction(net) ((net)->pkt_nr=0)
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -303,4 +303,5 @@
#define ER_CATALOG 1284 #define ER_CATALOG 1284
#define ER_WARN_QC_RESIZE 1285 #define ER_WARN_QC_RESIZE 1285
#define ER_BAD_FT_COLUMN 1286 #define ER_BAD_FT_COLUMN 1286
#define ER_ERROR_MESSAGES 287 #define ER_UNKNOWN_KEY_CACHE 1287
#define ER_ERROR_MESSAGES 288

View File

@ -1629,9 +1629,6 @@ NetWare. */
srv_file_per_table = srv_file_per_table_original_value; 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); return((int) DB_SUCCESS);
} }

View File

@ -1088,10 +1088,20 @@ mysql_refresh(MYSQL *mysql,uint options)
int STDCALL int STDCALL
mysql_kill(MYSQL *mysql,ulong pid) mysql_kill(MYSQL *mysql,ulong pid)
{ {
char buff[12]; char buff[4];
DBUG_ENTER("mysql_kill"); DBUG_ENTER("mysql_kill");
int4store(buff,pid); 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));
} }

View File

@ -67,6 +67,7 @@ EXPORTS
mysql_init mysql_init
mysql_insert_id mysql_insert_id
mysql_kill mysql_kill
mysql_set_server_option
mysql_list_dbs mysql_list_dbs
mysql_list_fields mysql_list_fields
mysql_list_processes mysql_list_processes

View File

@ -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) if (flags & FT_EXPAND && ft_query_expansion_limit)
{ {
QUEUE best; 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, tree_walk(&aio.dtree, (tree_walk_action) &walk_and_push,
&best, left_root_right); &best, left_root_right);
while (best.elements) while (best.elements)

View File

@ -53,13 +53,17 @@ const struct _ft_vft _ft_vft_boolean = {
ft_boolean_get_relevance, ft_boolean_reinit_search ft_boolean_get_relevance, ft_boolean_reinit_search
}; };
FT_INFO *ft_init_search(uint flags, void *info, uint keynr, FT_INFO *ft_init_search(uint flags, void *info, uint keynr,
byte *query, uint query_len, byte *record) byte *query, uint query_len, byte *record)
{ {
FT_INFO *res;
if (flags & FT_BOOL) 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 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; const char *ft_stopword_file = 0;

View File

@ -77,6 +77,7 @@ void myisamchk_init(MI_CHECK *param)
param->tmpfile_createflag=O_RDWR | O_TRUNC | O_EXCL; param->tmpfile_createflag=O_RDWR | O_TRUNC | O_EXCL;
param->myf_rw=MYF(MY_NABP | MY_WME | MY_WAIT_IF_FULL); param->myf_rw=MYF(MY_NABP | MY_WME | MY_WAIT_IF_FULL);
param->start_check_pos=0; param->start_check_pos=0;
param->key_cache_block_size= KEY_CACHE_BLOCK_SIZE;
} }
/* Check the status flags for the table */ /* 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 || if (next_link > info->state->key_file_length ||
next_link & (info->s->blocksize-1)) next_link & (info->s->blocksize-1))
DBUG_RETURN(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, info->s->kfile, next_link, DFLT_INIT_HITS,
(byte*) info->buff, (byte*) info->buff,
myisam_block_size, block_size, 1))) 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"); 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 */ info->s->kfile, FLUSH_FORCE_WRITE); /* If called externally */
size=my_seek(info->s->kfile,0L,MY_SEEK_END,MYF(0)); 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 */ param->testflag|=T_REP; /* for easy checking */
if (!param->using_global_keycache) if (!param->using_global_keycache)
VOID(init_key_cache(dflt_keycache,dflt_key_cache_var.block_size, VOID(init_key_cache(dflt_keycache, param->key_cache_block_size,
param->use_buffers,&dflt_key_cache_var)); param->use_buffers, &dflt_key_cache_var));
if (init_io_cache(&param->read_cache,info->dfile, if (init_io_cache(&param->read_cache,info->dfile,
(uint) param->read_buffer_length, (uint) param->read_buffer_length,
@ -1364,7 +1365,7 @@ err:
VOID(end_io_cache(&param->read_cache)); VOID(end_io_cache(&param->read_cache));
info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED); info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
VOID(end_io_cache(&info->rec_cache)); 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) if (!got_error && param->testflag & T_UNPACK)
{ {
share->state.header.options[0]&= (uchar) ~HA_OPTION_COMPRESS_RECORD; 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 */ /* 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); mi_check_print_error(param,"%d when trying to write bufferts",my_errno);
return(1); return(1);
} }
if (!param->using_global_keycache) if (!param->using_global_keycache)
end_key_cache(dflt_keycache,1); end_key_cache(key_cache,1);
return 0; return 0;
} /* flush_blocks */ } /* 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 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); share->state.version=(ulong) time((time_t*) 0);
old_state= share->state; /* save state if not stored */ 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 Flush key cache for this file if we are calling this outside
myisamchk 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 */ /* Clear the pointers to the given rows */
for (i=0 ; i < share->base.keys ; i++) for (i=0 ; i < share->base.keys ; i++)
share->state.key_root[i]= HA_OFFSET_ERROR; 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 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; goto err;
key_map= ~key_map; /* Create the missing keys */ 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)); memcpy( &share->state.state, info->state, sizeof(*info->state));
err: 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)); VOID(end_io_cache(&info->rec_cache));
if (!got_error) 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 Flush key cache for this file if we are calling this outside
myisamchk 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 */ /* Clear the pointers to the given rows */
for (i=0 ; i < share->base.keys ; i++) for (i=0 ; i < share->base.keys ; i++)
share->state.key_root[i]= HA_OFFSET_ERROR; share->state.key_root[i]= HA_OFFSET_ERROR;
@ -2246,7 +2247,7 @@ int mi_repair_parallel(MI_CHECK *param, register MI_INFO *info,
} }
else 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; goto err;
key_map= ~key_map; /* Create the missing keys */ 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)); memcpy(&share->state.state, info->state, sizeof(*info->state));
err: 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)); VOID(end_io_cache(&info->rec_cache));
if (!got_error) if (!got_error)
{ {
@ -3087,7 +3088,8 @@ int sort_write_record(MI_SORT_PARAM *sort_param)
(info->state->records % WRITE_COUNT) == 0) (info->state->records % WRITE_COUNT) == 0)
{ {
char llbuff[22]; 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); DBUG_RETURN(0);

View File

@ -27,7 +27,6 @@ ha_checksum mi_checksum(MI_INFO *info, const byte *buf)
for (i=info->s->base.fields ; i-- ; buf+=(rec++)->length) for (i=info->s->base.fields ; i-- ; buf+=(rec++)->length)
{ {
const byte *pos; const byte *pos;
const byte *end;
ulong length; ulong length;
switch (rec->type) { switch (rec->type) {
case FIELD_BLOB: case FIELD_BLOB:

View File

@ -64,7 +64,7 @@ int mi_close(register MI_INFO *info)
if (flag) if (flag)
{ {
if (share->kfile >= 0 && if (share->kfile >= 0 &&
flush_key_blocks(*share->keycache,share->kfile, flush_key_blocks(*share->key_cache, share->kfile,
share->temporary ? FLUSH_IGNORE_CHANGED : share->temporary ? FLUSH_IGNORE_CHANGED :
FLUSH_RELEASE)) FLUSH_RELEASE))
error=my_errno; error=my_errno;

View File

@ -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 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 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)) || if (my_chsize(info->dfile, 0, 0, MYF(MY_WME)) ||
my_chsize(share->kfile, share->base.keystart, 0, MYF(MY_WME)) ) my_chsize(share->kfile, share->base.keystart, 0, MYF(MY_WME)) )
goto err; goto err;

View File

@ -329,7 +329,7 @@ int mi_extra(MI_INFO *info, enum ha_extra_function function, void *extra_arg)
break; break;
case HA_EXTRA_FLUSH: case HA_EXTRA_FLUSH:
if (!share->temporary) 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 #ifdef HAVE_PWRITE
_mi_decrement_open_count(info); _mi_decrement_open_count(info);
#endif #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: case HA_EXTRA_PRELOAD_BUFFER_SIZE:
info->preload_buff_size= *((ulong *) extra_arg); info->preload_buff_size= *((ulong *) extra_arg);
break; 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_KEY_CACHE:
case HA_EXTRA_NO_KEY_CACHE: case HA_EXTRA_NO_KEY_CACHE:
default: default:

View File

@ -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 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 it under the terms of the GNU General Public License as published by
@ -20,88 +20,136 @@
#include "myisamdef.h" #include "myisamdef.h"
/* /*
Assign pages of the index file for a table to a key cache Assign pages of the index file for a table to a key cache
SYNOPSIS SYNOPSIS
mi_assign_to_keycache() mi_assign_to_key_cache()
info open table 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 key_cache_ptr pointer to the key cache handle
assign_lock Mutex to lock during assignment
RETURN VALUE PREREQUESTS
0 if a success. error code - otherwise. 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. 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 In future only pages for indexes specified in the key_map parameter
of the table will be assigned to the specified key cache. of the table will be assigned to the specified key cache.
RETURN VALUE
0 If a success
# Error code
*/ */
typedef struct st_assign_extra_info int mi_assign_to_key_cache(MI_INFO *info,
ulonglong key_map __attribute__((unused)),
KEY_CACHE_VAR *key_cache)
{ {
pthread_mutex_t *lock;
struct st_my_thread_var *waiting_thread;
} ASSIGN_EXTRA_INFO;
static void remove_key_cache_assign(void *arg)
{
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))
{
my_free(extra_info, MYF(0));
key_cache->extra_info= 0;
if (waiting_thread != my_thread_var)
pthread_cond_signal(&waiting_thread->suspend);
}
pthread_mutex_unlock(lock);
}
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; int error= 0;
MYISAM_SHARE* share= info->s; 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));
DBUG_ENTER("mi_assign_to_keycache"); /*
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);
share->reg_keycache= &key_cache->cache; /*
pthread_mutex_lock(assign_lock); First flush all blocks for the table in the old key cache.
if (!(extra_info= (ASSIGN_EXTRA_INFO *) key_cache->extra_info)) 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))
{ {
if (!(extra_info= (ASSIGN_EXTRA_INFO*) my_malloc(sizeof(ASSIGN_EXTRA_INFO), error= my_errno;
MYF(MY_WME | MY_ZEROFILL)))) mi_mark_crashed(info); /* Mark that table must be checked */
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
{
extra_info->waiting_thread= my_thread_var;
} }
/*
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); DBUG_RETURN(error);
} }
/*
Change all MyISAM entries that uses one key cache to another key cache
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)
{
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);
}
/*
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);
}

View File

@ -34,7 +34,6 @@ int mi_lock_database(MI_INFO *info, int lock_type)
uint count; uint count;
MYISAM_SHARE *share=info->s; MYISAM_SHARE *share=info->s;
uint flag; uint flag;
uint switch_fl= 0;
DBUG_ENTER("mi_lock_database"); DBUG_ENTER("mi_lock_database");
DBUG_PRINT("info",("lock_type: %d", lock_type)); DBUG_PRINT("info",("lock_type: %d", lock_type));
@ -61,21 +60,13 @@ int mi_lock_database(MI_INFO *info, int lock_type)
else else
count= --share->w_locks; count= --share->w_locks;
--share->tot_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 && if (info->lock_type == F_WRLCK && !share->w_locks &&
((switch_fl= share->keycache != share->reg_keycache) || !share->delay_key_write && flush_key_blocks(*share->key_cache,
!share->delay_key_write) && share->kfile,FLUSH_KEEP))
flush_key_blocks(*share->keycache, share->kfile,
switch_fl ? FLUSH_REMOVE : FLUSH_KEEP))
{ {
error=my_errno; error=my_errno;
mi_mark_crashed(info); /* Mark that table must be checked */ 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 (info->opt_flag & (READ_CACHE_USED | WRITE_CACHE_USED))
{ {
if (end_io_cache(&info->rec_cache)) if (end_io_cache(&info->rec_cache))
@ -398,7 +389,7 @@ int _mi_test_if_changed(register MI_INFO *info)
{ /* Keyfile has changed */ { /* Keyfile has changed */
DBUG_PRINT("info",("index file changed")); DBUG_PRINT("info",("index file changed"));
if (share->state.process != share->this_process) 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; share->last_process=share->state.process;
info->last_unique= share->state.unique; info->last_unique= share->state.unique;
info->last_loop= share->state.update_count; info->last_loop= share->state.update_count;

View File

@ -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.rec_per_key_part=rec_per_key_part;
share_buff.state.key_root=key_root; share_buff.state.key_root=key_root;
share_buff.state.key_del=key_del; 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) 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) * (char*) key_del, (sizeof(my_off_t) *
share->state.header.max_block_size)); share->state.header.max_block_size));
strmov(share->unique_file_name, name_buff); strmov(share->unique_file_name, name_buff);
share->unique_name_length= strlen(name_buff);
strmov(share->index_file_name, index_name); strmov(share->index_file_name, index_name);
strmov(share->data_file_name, data_name); strmov(share->data_file_name, data_name);

View File

@ -32,7 +32,7 @@ uchar *_mi_fetch_keypage(register MI_INFO *info, MI_KEYDEF *keyinfo,
DBUG_ENTER("_mi_fetch_keypage"); DBUG_ENTER("_mi_fetch_keypage");
DBUG_PRINT("enter",("page: %ld",page)); 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, info->s->kfile, page, level, (byte*) buff,
(uint) keyinfo->block_length, (uint) keyinfo->block_length,
(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", DBUG_PRINT("error",("page %lu had wrong page length: %u",
(ulong) page, page_size)); (ulong) page, page_size));
DBUG_DUMP("page", tmp, keyinfo->block_length);
info->last_keypage = HA_OFFSET_ERROR; info->last_keypage = HA_OFFSET_ERROR;
my_errno = HA_ERR_CRASHED; my_errno = HA_ERR_CRASHED;
tmp = 0; tmp = 0;
@ -94,7 +95,7 @@ int _mi_write_keypage(register MI_INFO *info, register MI_KEYDEF *keyinfo,
length=keyinfo->block_length; length=keyinfo->block_length;
} }
#endif #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, info->s->kfile,page, level, (byte*) buff,length,
(uint) keyinfo->block_length, (uint) keyinfo->block_length,
(int) ((info->lock_type != F_UNLCK) || (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; info->s->state.key_del[keyinfo->block_size]=pos;
mi_sizestore(buff,old_link); mi_sizestore(buff,old_link);
info->s->state.changed|= STATE_NOT_SORTED_PAGES; 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, info->s->kfile, pos , level, buff,
sizeof(buff), sizeof(buff),
(uint) keyinfo->block_length, (uint) keyinfo->block_length,
@ -145,7 +146,7 @@ my_off_t _mi_new(register MI_INFO *info, MI_KEYDEF *keyinfo, int level)
} }
else else
{ {
if (!key_cache_read(*info->s->keycache, if (!key_cache_read(*info->s->key_cache,
info->s->kfile, pos, level, info->s->kfile, pos, level,
buff, buff,
(uint) sizeof(buff), (uint) sizeof(buff),

View File

@ -48,7 +48,7 @@ int mi_panic(enum ha_panic_function flag)
if (info->s->options & HA_OPTION_READ_ONLY_DATA) if (info->s->options & HA_OPTION_READ_ONLY_DATA)
break; break;
#endif #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; error=my_errno;
if (info->opt_flag & WRITE_CACHE_USED) if (info->opt_flag & WRITE_CACHE_USED)
if (flush_io_cache(&info->rec_cache)) if (flush_io_cache(&info->rec_cache))

View File

@ -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)))) if (!(buff= (uchar *) my_malloc(length, MYF(MY_WME))))
DBUG_RETURN(my_errno= HA_ERR_OUT_OF_MEM); 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; goto err;
do 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 (mi_test_if_nod(buff))
{ {
if (key_cache_insert(*share->keycache, if (key_cache_insert(*share->key_cache,
share->kfile, pos, DFLT_INIT_HITS, share->kfile, pos, DFLT_INIT_HITS,
(byte*) buff, block_length)) (byte*) buff, block_length))
goto err; goto err;
@ -99,7 +99,7 @@ int mi_preload(MI_INFO *info, ulonglong key_map, my_bool ignore_leaves)
} }
else else
{ {
if (key_cache_insert(*share->keycache, if (key_cache_insert(*share->key_cache,
share->kfile, pos, DFLT_INIT_HITS, share->kfile, pos, DFLT_INIT_HITS,
(byte*) buff, length)) (byte*) buff, length))
goto err; goto err;

View File

@ -50,7 +50,7 @@ int main(int argc,char *argv[])
MY_INIT(argv[0]); MY_INIT(argv[0]);
my_init(); my_init();
if (key_cacheing) 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); get_options(argc,argv);
exit(run_test("test1")); exit(run_test("test1"));

View File

@ -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, static int pack_seg=HA_SPACE_PACK,pack_type=HA_PACK_KEY,remove_count=-1,
create_flag=0; create_flag=0;
static ulong key_cache_size=IO_SIZE*16; 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 keys=MYISAM_KEYS,recant=1000;
static uint use_blob=0; 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)"); puts("got error from mi_extra(HA_EXTRA_NO_CACHE)");
goto end; 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) if (!silent)
printf("- Delete\n"); printf("- Delete\n");
@ -829,7 +829,7 @@ reads: %10lu\n",
my_cache_r_requests, my_cache_read); my_cache_r_requests, my_cache_read);
#endif #endif
} }
end_key_cache(dflt_keycache,1); end_key_cache(*dflt_keycache,1);
if (blob_buffer) if (blob_buffer)
my_free(blob_buffer,MYF(0)); my_free(blob_buffer,MYF(0));
my_end(silent ? MY_CHECK_ERROR : MY_CHECK_ERROR | MY_GIVE_INFO); my_end(silent ? MY_CHECK_ERROR : MY_CHECK_ERROR | MY_GIVE_INFO);

View File

@ -177,7 +177,7 @@ void start_test(int id)
exit(1); exit(1);
} }
if (key_cacheing && rnd(2) == 0) 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); printf("Process %d, pid: %d\n",id,getpid()); fflush(stdout);
for (error=i=0 ; i < tests && !error; i++) for (error=i=0 ; i < tests && !error; i++)

View File

@ -715,6 +715,7 @@ static void get_options(register int *argc,register char ***argv)
exit(1); exit(1);
check_param.tmpdir=&myisamchk_tmpdir; check_param.tmpdir=&myisamchk_tmpdir;
check_param.key_cache_block_size= opt_key_cache_block_size;
if (set_charset_name) if (set_charset_name)
if (!(set_charset=get_charset_by_name(set_charset_name, MYF(MY_WME)))) 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)) || HA_OPTION_COMPRESS_RECORD)) ||
(param->testflag & (T_EXTEND | T_MEDIUM))) (param->testflag & (T_EXTEND | T_MEDIUM)))
error|=chk_data_link(param, info, param->testflag & T_EXTEND); 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)); VOID(end_io_cache(&param->read_cache));
} }
if (!error) if (!error)
@ -1455,7 +1456,7 @@ static int mi_sort_records(MI_CHECK *param,
if (share->state.key_root[sort_key] == HA_OFFSET_ERROR) if (share->state.key_root[sort_key] == HA_OFFSET_ERROR)
DBUG_RETURN(0); /* Nothing to do */ 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); &dflt_key_cache_var);
if (init_io_cache(&info->rec_cache,-1,(uint) param->write_buffer_length, if (init_io_cache(&info->rec_cache,-1,(uint) param->write_buffer_length,
WRITE_CACHE,share->pack.header_length,1, WRITE_CACHE,share->pack.header_length,1,
@ -1570,7 +1571,8 @@ err:
my_free(sort_info.buff,MYF(MY_ALLOW_ZERO_PTR)); my_free(sort_info.buff,MYF(MY_ALLOW_ZERO_PTR));
sort_info.buff=0; sort_info.buff=0;
share->state.sortkey=sort_key; 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 */ } /* sort_records */

View File

@ -166,8 +166,7 @@ typedef struct st_mi_isam_share { /* Shared between opens */
char *data_file_name, /* Resolved path names from symlinks */ char *data_file_name, /* Resolved path names from symlinks */
*index_file_name; *index_file_name;
byte *file_map; /* mem-map of file if possible */ byte *file_map; /* mem-map of file if possible */
KEY_CACHE_HANDLE *keycache; /* ref to the current key cache */ KEY_CACHE_HANDLE *key_cache; /* ref to the current key cache */
KEY_CACHE_HANDLE *reg_keycache; /* ref to the registered key cache */
MI_DECODE_TREE *decode_trees; MI_DECODE_TREE *decode_trees;
uint16 *decode_tables; uint16 *decode_tables;
int (*read_record)(struct st_myisam_info*, my_off_t, byte*); 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 max_pack_length;
ulong state_diff_length; ulong state_diff_length;
uint rec_reflength; /* rec_reflength in use now */ uint rec_reflength; /* rec_reflength in use now */
uint unique_name_length;
File kfile; /* Shared keyfile */ File kfile; /* Shared keyfile */
File data_file; /* Shared data file */ File data_file; /* Shared data file */
int mode; /* mode of file on open */ int mode; /* mode of file on open */
@ -713,6 +713,7 @@ int thr_write_keys(MI_SORT_PARAM *sort_param);
#ifdef THREAD #ifdef THREAD
pthread_handler_decl(thr_find_all_keys,arg); pthread_handler_decl(thr_find_all_keys,arg);
#endif #endif
int flush_blocks(MI_CHECK *param, KEY_CACHE_HANDLE key_cache, File file);
int sort_write_record(MI_SORT_PARAM *sort_param); int sort_write_record(MI_SORT_PARAM *sort_param);
int _create_index_by_sort(MI_SORT_PARAM *info,my_bool no_messages, ulong); int _create_index_by_sort(MI_SORT_PARAM *info,my_bool no_messages, ulong);

View File

@ -648,7 +648,7 @@ static int examine_log(my_string file_name, char **table_names)
goto end; goto end;
} }
} }
end_key_cache(dflt_keycache,1); end_key_cache(*dflt_keycache,1);
delete_tree(&tree); delete_tree(&tree);
VOID(end_io_cache(&cache)); VOID(end_io_cache(&cache));
VOID(my_close(file,MYF(0))); 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))); llstr(isamlog_filepos,llbuff)));
fflush(stderr); fflush(stderr);
end: end:
end_key_cache(dflt_keycache,1); end_key_cache(*dflt_keycache, 1);
delete_tree(&tree); delete_tree(&tree);
VOID(end_io_cache(&cache)); VOID(end_io_cache(&cache));
VOID(my_close(file,MYF(0))); VOID(my_close(file,MYF(0)));

View File

@ -575,7 +575,7 @@ show_failed_diff ()
$DIFF -c $result_file $reject_file $DIFF -c $result_file $reject_file
echo "-------------------------------------------------------" echo "-------------------------------------------------------"
echo "Please follow the instructions outlined at" 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." echo "to find the reason to this problem and how to report this."
fi fi
} }
@ -1311,7 +1311,7 @@ run_testcase ()
show_failed_diff $tname show_failed_diff $tname
$ECHO $ECHO
if [ x$FORCE != x1 ] ; then 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 $ECHO
if [ -z "$DO_GDB" ] && [ -z "$USE_RUNNING_SERVER" ] && [ -z "$DO_DDD" ] if [ -z "$DO_GDB" ] && [ -z "$USE_RUNNING_SERVER" ] && [ -z "$DO_DDD" ]
then then

View File

@ -319,6 +319,29 @@ alter table t1 change a a char(10) character set koi8r;
select a,hex(a) from t1; select a,hex(a) from t1;
a hex(a) a hex(a)
<EFBFBD><EFBFBD><EFBFBD><EFBFBD> D4C5D3D4 <EFBFBD><EFBFBD><EFBFBD><EFBFBD> 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; drop table t1;
CREATE TABLE t1 ( CREATE TABLE t1 (
Host varchar(16) binary NOT NULL default '', Host varchar(16) binary NOT NULL default '',

View File

@ -103,7 +103,7 @@ t1 CREATE TABLE `t1` (
`c6` char(3) default NULL, `c6` char(3) default NULL,
`c7` double(3,1) default NULL, `c7` double(3,1) default NULL,
`c8` double(3,1) default NULL `c8` double(3,1) default NULL
) TYPE=MyISAM CHARSET=latin1 ) TYPE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1; DROP TABLE t1;
SELECT CASE SELECT CASE
WHEN 1 WHEN 1
@ -150,5 +150,5 @@ t1 CREATE TABLE `t1` (
`COALESCE(1,'1')` char(1) NOT NULL default '', `COALESCE(1,'1')` char(1) NOT NULL default '',
`COALESCE(1.1,'1')` char(3) 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 '' `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; DROP TABLE t1;

View File

@ -45,7 +45,7 @@ show create table t1;
Table Create Table Table Create Table
t1 CREATE TABLE `t1` ( t1 CREATE TABLE `t1` (
`t` char(4) character set cp1251 NOT NULL default '' `t` char(4) character set cp1251 NOT NULL default ''
) TYPE=MyISAM CHARSET=latin1 ) TYPE=MyISAM DEFAULT CHARSET=latin1
drop table t1; drop table t1;
select select
cast(_latin1'ab' AS char) as c1, cast(_latin1'ab' AS char) as c1,
@ -72,7 +72,7 @@ t1 CREATE TABLE `t1` (
`c3` char(2) binary NOT NULL default '', `c3` char(2) binary NOT NULL default '',
`c4` char(2) binary NOT NULL default '', `c4` char(2) binary NOT NULL default '',
`c5` 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; drop table t1;
select select
cast(_koi8r'<27><>' AS nchar) as c1, cast(_koi8r'<27><>' AS nchar) as c1,
@ -99,7 +99,7 @@ t1 CREATE TABLE `t1` (
`c3` char(2) character set utf8 NOT NULL default '', `c3` char(2) character set utf8 NOT NULL default '',
`c4` 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 '' `c5` char(2) character set utf8 NOT NULL default ''
) TYPE=MyISAM CHARSET=latin1 ) TYPE=MyISAM DEFAULT CHARSET=latin1
drop table t1; drop table t1;
select cast("2001-1-1" as date) = "2001-01-01"; select cast("2001-1-1" as date) = "2001-01-01";
cast("2001-1-1" as date) = "2001-01-01" cast("2001-1-1" as date) = "2001-01-01"

View File

@ -179,7 +179,7 @@ t1 CREATE TABLE `t1` (
KEY `b_29` (`b`), KEY `b_29` (`b`),
KEY `b_30` (`b`), KEY `b_30` (`b`),
KEY `b_31` (`b`) KEY `b_31` (`b`)
) TYPE=MyISAM CHARSET=latin1 ) TYPE=MyISAM DEFAULT CHARSET=latin1
drop table t1; drop table t1;
create table t1 select if(1,'1','0'), month("2002-08-02"); create table t1 select if(1,'1','0'), month("2002-08-02");
drop table t1; drop table t1;
@ -197,7 +197,7 @@ show create table t1;
Table Create Table Table Create Table
t1 CREATE TABLE `t1` ( t1 CREATE TABLE `t1` (
`a` int(11) NOT NULL default '0' `a` int(11) NOT NULL default '0'
) TYPE=HEAP CHARSET=latin1 ) TYPE=HEAP DEFAULT CHARSET=latin1
drop table t1; drop table t1;
SET SESSION table_type="gemini"; SET SESSION table_type="gemini";
SELECT @@table_type; SELECT @@table_type;
@ -210,7 +210,7 @@ show create table t1;
Table Create Table Table Create Table
t1 CREATE TABLE `t1` ( t1 CREATE TABLE `t1` (
`a` int(11) NOT NULL default '0' `a` int(11) NOT NULL default '0'
) TYPE=MyISAM CHARSET=latin1 ) TYPE=MyISAM DEFAULT CHARSET=latin1
SET SESSION table_type=default; SET SESSION table_type=default;
drop table t1; drop table t1;
create table t1 ( k1 varchar(2), k2 int, primary key(k1,k2)); create table t1 ( k1 varchar(2), k2 int, primary key(k1,k2));
@ -275,7 +275,7 @@ Table Create Table
t3 CREATE TABLE `t3` ( t3 CREATE TABLE `t3` (
`id` int(11) NOT NULL default '0', `id` int(11) NOT NULL default '0',
`name` char(20) default NULL `name` char(20) default NULL
) TYPE=MyISAM CHARSET=latin1 ) TYPE=MyISAM DEFAULT CHARSET=latin1
select * from t3; select * from t3;
id name id name
create table if not exists t3 like t1; create table if not exists t3 like t1;
@ -289,7 +289,7 @@ show create table t3;
Table Create Table Table Create Table
t3 CREATE TEMPORARY TABLE `t3` ( t3 CREATE TEMPORARY TABLE `t3` (
`id` int(11) NOT NULL default '0' `id` int(11) NOT NULL default '0'
) TYPE=MyISAM CHARSET=latin1 ) TYPE=MyISAM DEFAULT CHARSET=latin1
select * from t3; select * from t3;
id id
drop table t3; drop table t3;
@ -298,7 +298,7 @@ Table Create Table
t3 CREATE TABLE `t3` ( t3 CREATE TABLE `t3` (
`id` int(11) NOT NULL default '0', `id` int(11) NOT NULL default '0',
`name` char(20) default NULL `name` char(20) default NULL
) TYPE=MyISAM CHARSET=latin1 ) TYPE=MyISAM DEFAULT CHARSET=latin1
select * from t3; select * from t3;
id name id name
drop table t2, t3; drop table t2, t3;
@ -313,14 +313,14 @@ Table Create Table
t3 CREATE TEMPORARY TABLE `t3` ( t3 CREATE TEMPORARY TABLE `t3` (
`id` int(11) NOT NULL default '0', `id` int(11) NOT NULL default '0',
`name` char(20) default NULL `name` char(20) default NULL
) TYPE=MyISAM CHARSET=latin1 ) TYPE=MyISAM DEFAULT CHARSET=latin1
create table t2 like t3; create table t2 like t3;
show create table t2; show create table t2;
Table Create Table Table Create Table
t2 CREATE TABLE `t2` ( t2 CREATE TABLE `t2` (
`id` int(11) NOT NULL default '0', `id` int(11) NOT NULL default '0',
`name` char(20) default NULL `name` char(20) default NULL
) TYPE=MyISAM CHARSET=latin1 ) TYPE=MyISAM DEFAULT CHARSET=latin1
select * from t2; select * from t2;
id name id name
create table t3 like t1; create table t3 like t1;
@ -346,7 +346,7 @@ show create table t1;
Table Create Table Table Create Table
t1 CREATE TABLE `t1` ( t1 CREATE TABLE `t1` (
`a` int(11) NOT NULL default '0' `a` int(11) NOT NULL default '0'
) TYPE=HEAP CHARSET=latin1 ) TYPE=HEAP DEFAULT CHARSET=latin1
drop table t1; drop table t1;
SET SESSION table_type="gemini"; SET SESSION table_type="gemini";
SELECT @@table_type; SELECT @@table_type;
@ -359,7 +359,7 @@ show create table t1;
Table Create Table Table Create Table
t1 CREATE TABLE `t1` ( t1 CREATE TABLE `t1` (
`a` int(11) NOT NULL default '0' `a` int(11) NOT NULL default '0'
) TYPE=MyISAM CHARSET=latin1 ) TYPE=MyISAM DEFAULT CHARSET=latin1
SET SESSION table_type=default; SET SESSION table_type=default;
drop table t1; drop table t1;
create table t1(a int,b int,c int unsigned,d date,e char,f datetime,g time,h blob); create table t1(a int,b int,c int unsigned,d date,e char,f datetime,g time,h blob);

View File

@ -491,7 +491,7 @@ SHOW CREATE TABLE t1;
Table Create Table Table Create Table
t1 CREATE TABLE `t1` ( t1 CREATE TABLE `t1` (
`latin1_f` char(32) NOT NULL default '' `latin1_f` char(32) NOT NULL default ''
) TYPE=MyISAM CHARSET=latin1 ) TYPE=MyISAM DEFAULT CHARSET=latin1
SHOW FIELDS FROM t1; SHOW FIELDS FROM t1;
Field Type Null Key Default Extra Field Type Null Key Default Extra
latin1_f char(32) latin1_f char(32)
@ -501,7 +501,7 @@ SHOW CREATE TABLE t1;
Table Create Table Table Create Table
t1 CREATE TABLE `t1` ( t1 CREATE TABLE `t1` (
`latin1_f` char(32) character set latin1 collate latin1_bin default NULL `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; SHOW FIELDS FROM t1;
Field Type Null Key Default Extra Field Type Null Key Default Extra
latin1_f char(32) YES NULL latin1_f char(32) YES NULL
@ -509,8 +509,8 @@ ALTER TABLE t1 CHARACTER SET latin1 COLLATE latin1_bin;
SHOW CREATE TABLE t1; SHOW CREATE TABLE t1;
Table Create Table Table Create Table
t1 CREATE TABLE `t1` ( t1 CREATE TABLE `t1` (
`latin1_f` char(32) collate latin1_bin default NULL `latin1_f` char(32) character set latin1 collate latin1_bin default NULL
) TYPE=MyISAM CHARSET=latin1 COLLATE=latin1_bin ) TYPE=MyISAM DEFAULT CHARSET=latin1
SHOW FIELDS FROM t1; SHOW FIELDS FROM t1;
Field Type Null Key Default Extra Field Type Null Key Default Extra
latin1_f char(32) YES NULL latin1_f char(32) YES NULL

View File

@ -225,7 +225,7 @@ t1 CREATE TABLE `t1` (
`word` varchar(255) collate latin1_german2_ci NOT NULL default '', `word` varchar(255) collate latin1_german2_ci NOT NULL default '',
`word2` varchar(255) collate latin1_german2_ci NOT NULL default '', `word2` varchar(255) collate latin1_german2_ci NOT NULL default '',
KEY `word` (`word`) 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'); insert into t1 (word) values ('ss'),(0xDF),(0xE4),('ae');
update t1 set word2=word; update t1 set word2=word;
select word, word=binary 0xdf as t from t1 having t > 0; select word, word=binary 0xdf as t from t1 having t > 0;
@ -284,7 +284,7 @@ show create table t1;
Table Create Table Table Create Table
t1 CREATE TABLE `t1` ( t1 CREATE TABLE `t1` (
`s1` char(5) collate latin1_german2_ci default NULL `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 ('<27>'); INSERT INTO t1 VALUES ('<27>');
INSERT INTO t1 VALUES ('ue'); INSERT INTO t1 VALUES ('ue');
SELECT DISTINCT s1 FROM t1; SELECT DISTINCT s1 FROM t1;

View File

@ -9,14 +9,14 @@ Table Create Table
t1 CREATE TABLE `t1` ( t1 CREATE TABLE `t1` (
`comment` char(32) character set latin1 NOT NULL default '', `comment` char(32) character set latin1 NOT NULL default '',
`koi8_ru_f` char(32) character set koi8r 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; ALTER TABLE t1 CHANGE comment comment CHAR(32) CHARACTER SET latin2 NOT NULL;
SHOW CREATE TABLE t1; SHOW CREATE TABLE t1;
Table Create Table Table Create Table
t1 CREATE TABLE `t1` ( t1 CREATE TABLE `t1` (
`comment` char(32) character set latin2 NOT NULL default '', `comment` char(32) character set latin2 NOT NULL default '',
`koi8_ru_f` char(32) character set koi8r 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; ALTER TABLE t1 ADD latin5_f CHAR(32) NOT NULL;
SHOW CREATE TABLE t1; SHOW CREATE TABLE t1;
Table Create Table Table Create Table
@ -24,8 +24,8 @@ t1 CREATE TABLE `t1` (
`comment` char(32) character set latin2 NOT NULL default '', `comment` char(32) character set latin2 NOT NULL default '',
`koi8_ru_f` char(32) character set koi8r NOT NULL default '', `koi8_ru_f` char(32) character set koi8r NOT NULL default '',
`latin5_f` char(32) NOT NULL default '' `latin5_f` char(32) NOT NULL default ''
) TYPE=MyISAM CHARSET=latin5 ) TYPE=MyISAM DEFAULT CHARSET=latin5
ALTER TABLE t1 CHARSET=latin2; ALTER TABLE t1 DEFAULT CHARSET=latin2;
ALTER TABLE t1 ADD latin2_f CHAR(32) NOT NULL; ALTER TABLE t1 ADD latin2_f CHAR(32) NOT NULL;
SHOW CREATE TABLE t1; SHOW CREATE TABLE t1;
Table Create Table Table Create Table
@ -34,14 +34,14 @@ t1 CREATE TABLE `t1` (
`koi8_ru_f` char(32) character set koi8r NOT NULL default '', `koi8_ru_f` char(32) character set koi8r NOT NULL default '',
`latin5_f` char(32) character set latin5 NOT NULL default '', `latin5_f` char(32) character set latin5 NOT NULL default '',
`latin2_f` char(32) 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; ALTER TABLE t1 DROP latin2_f, DROP latin5_f;
SHOW CREATE TABLE t1; SHOW CREATE TABLE t1;
Table Create Table Table Create Table
t1 CREATE TABLE `t1` ( t1 CREATE TABLE `t1` (
`comment` char(32) NOT NULL default '', `comment` char(32) NOT NULL default '',
`koi8_ru_f` char(32) character set koi8r 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 ('a','LAT SMALL A');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('b','LAT SMALL B'); INSERT INTO t1 (koi8_ru_f,comment) VALUES ('b','LAT SMALL B');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('c','LAT SMALL C'); INSERT INTO t1 (koi8_ru_f,comment) VALUES ('c','LAT SMALL C');

View File

@ -5,7 +5,7 @@ Table Create Table
t1 CREATE TABLE `t1` ( t1 CREATE TABLE `t1` (
`c1` char(4) character set utf8 NOT NULL default '', `c1` char(4) character set utf8 NOT NULL default '',
`c2` 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; DELETE FROM t1;
ALTER TABLE t1 ADD c3 CHAR(4) CHARACTER SET utf8; ALTER TABLE t1 ADD c3 CHAR(4) CHARACTER SET utf8;
SHOW CREATE TABLE t1; SHOW CREATE TABLE t1;
@ -14,7 +14,7 @@ t1 CREATE TABLE `t1` (
`c1` char(4) character set utf8 NOT NULL default '', `c1` char(4) character set utf8 NOT NULL default '',
`c2` 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 `c3` char(4) character set utf8 default NULL
) TYPE=MyISAM CHARSET=latin1 ) TYPE=MyISAM DEFAULT CHARSET=latin1
INSERT INTO t1 VALUES ('aaaabbbbccccdddd','aaaabbbbccccdddd','aaaabbbbccccdddd'); INSERT INTO t1 VALUES ('aaaabbbbccccdddd','aaaabbbbccccdddd','aaaabbbbccccdddd');
Warnings: Warnings:
Warning 1264 Data truncated for column 'c1' at row 1 Warning 1264 Data truncated for column 'c1' at row 1
@ -30,7 +30,7 @@ Table Create Table
t1 CREATE TABLE `t1` ( t1 CREATE TABLE `t1` (
`a` char(4) character set utf8 default NULL, `a` char(4) character set utf8 default NULL,
KEY `key_a` (`a`(3)) KEY `key_a` (`a`(3))
) TYPE=MyISAM CHARSET=latin1 ) TYPE=MyISAM DEFAULT CHARSET=latin1
SHOW KEYS FROM t1; SHOW KEYS FROM t1;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment 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 t1 1 key_a 1 a A NULL 9 NULL YES BTREE
@ -40,7 +40,7 @@ Table Create Table
t1 CREATE TABLE `t1` ( t1 CREATE TABLE `t1` (
`a` char(4) default NULL, `a` char(4) default NULL,
KEY `key_a` (`a`(3)) KEY `key_a` (`a`(3))
) TYPE=MyISAM CHARSET=latin1 ) TYPE=MyISAM DEFAULT CHARSET=latin1
SHOW KEYS FROM t1; SHOW KEYS FROM t1;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment 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 t1 1 key_a 1 a A NULL 3 NULL YES BTREE
@ -50,7 +50,7 @@ Table Create Table
t1 CREATE TABLE `t1` ( t1 CREATE TABLE `t1` (
`a` char(4) character set utf8 default NULL, `a` char(4) character set utf8 default NULL,
KEY `key_a` (`a`(3)) KEY `key_a` (`a`(3))
) TYPE=MyISAM CHARSET=latin1 ) TYPE=MyISAM DEFAULT CHARSET=latin1
SHOW KEYS FROM t1; SHOW KEYS FROM t1;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment 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 t1 1 key_a 1 a A NULL 9 NULL YES BTREE

View File

@ -6,7 +6,7 @@ SHOW CREATE TABLE t1;
Table Create Table Table Create Table
t1 CREATE TABLE `t1` ( t1 CREATE TABLE `t1` (
`a` char(10) character set cp1251 default NULL `a` char(10) character set cp1251 default NULL
) TYPE=MyISAM CHARSET=latin1 ) TYPE=MyISAM DEFAULT CHARSET=latin1
SELECT a FROM t1; SELECT a FROM t1;
a a
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
@ -25,7 +25,7 @@ SHOW CREATE TABLE
Table Create Table Table Create Table
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> CREATE TABLE `<60><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>` ( <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> CREATE TABLE `<60><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>` (
`<60><><EFBFBD><EFBFBD>` char(32) character set koi8r NOT NULL default '' COMMENT '<27><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>' `<60><><EFBFBD><EFBFBD>` char(32) character set koi8r NOT NULL default '' COMMENT '<27><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>'
) TYPE=MyISAM CHARSET=latin1 COMMENT='<27><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>' ) TYPE=MyISAM DEFAULT CHARSET=latin1 COMMENT='<27><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>'
SHOW FIELDS FROM <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>; SHOW FIELDS FROM <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>;
Field Type Null Key Default Extra Field Type Null Key Default Extra
<EFBFBD><EFBFBD><EFBFBD><EFBFBD> char(32) <EFBFBD><EFBFBD><EFBFBD><EFBFBD> char(32)
@ -37,7 +37,7 @@ SHOW CREATE TABLE
Table Create Table Table Create Table
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> CREATE TABLE `<60><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>` ( <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> CREATE TABLE `<60><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>` (
`<60><><EFBFBD><EFBFBD>` char(32) character set koi8r NOT NULL default '' COMMENT '<27><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>' `<60><><EFBFBD><EFBFBD>` char(32) character set koi8r NOT NULL default '' COMMENT '<27><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>'
) TYPE=MyISAM CHARSET=latin1 COMMENT='<27><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>' ) TYPE=MyISAM DEFAULT CHARSET=latin1 COMMENT='<27><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>'
SHOW FIELDS FROM <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>; SHOW FIELDS FROM <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>;
Field Type Null Key Default Extra Field Type Null Key Default Extra
<EFBFBD><EFBFBD><EFBFBD><EFBFBD> char(32) <EFBFBD><EFBFBD><EFBFBD><EFBFBD> char(32)
@ -49,7 +49,7 @@ SHOW CREATE TABLE таблица;
Table Create Table Table Create Table
таблица CREATE TABLE `таблица` ( таблица CREATE TABLE `таблица` (
`поле` char(32) character set koi8r NOT NULL default '' COMMENT 'комментарий поля' `поле` char(32) character set koi8r NOT NULL default '' COMMENT 'комментарий поля'
) TYPE=MyISAM CHARSET=latin1 COMMENT='комментарий таблицы' ) TYPE=MyISAM DEFAULT CHARSET=latin1 COMMENT='комментарий таблицы'
SHOW FIELDS FROM таблица; SHOW FIELDS FROM таблица;
Field Type Null Key Default Extra Field Type Null Key Default Extra
поле char(32) поле char(32)

View File

@ -45,7 +45,7 @@ Table Create Table
t1 CREATE TABLE `t1` ( t1 CREATE TABLE `t1` (
`l` char(10) character set ucs2 NOT NULL default '', `l` char(10) character set ucs2 NOT NULL default '',
`r` 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; DROP TABLE t1;
SET NAMES koi8r; SET NAMES koi8r;
SET character_set_connection=ucs2; SET character_set_connection=ucs2;

View File

@ -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); 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 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); 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 pla_id mat_id
100 1 100 1
101 1 101 1
@ -172,7 +172,7 @@ pla_id mat_id
103 2 103 2
104 2 104 2
105 3 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 pla_id test
100 1 100 1
101 1 101 1
@ -180,13 +180,13 @@ pla_id test
103 2 103 2
104 2 104 2
105 3 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 id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY m2 ALL NULL NULL NULL NULL 9 1 PRIMARY m2 ALL NULL NULL NULL NULL 9
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 6 Using where 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 mp ALL NULL NULL NULL NULL 9 Using temporary; Using filesort
2 DERIVED m2 index NULL PRIMARY 3 NULL 9 Using index 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 id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY m2 ALL NULL NULL NULL NULL 9 1 PRIMARY m2 ALL NULL NULL NULL NULL 9
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 6 Using where 1 PRIMARY <derived2> ALL NULL NULL NULL NULL 6 Using where

View File

@ -201,7 +201,7 @@ t2 CREATE TABLE `t2` (
`inhalt` text, `inhalt` text,
KEY `tig` (`ticket`), KEY `tig` (`ticket`),
FULLTEXT KEY `tix` (`inhalt`) FULLTEXT KEY `tix` (`inhalt`)
) TYPE=MyISAM CHARSET=latin1 ) TYPE=MyISAM DEFAULT CHARSET=latin1
select * from t2 where MATCH inhalt AGAINST (NULL); select * from t2 where MATCH inhalt AGAINST (NULL);
ticket inhalt ticket inhalt
select * from t2 where MATCH inhalt AGAINST ('foobar'); select * from t2 where MATCH inhalt AGAINST ('foobar');

View File

@ -539,7 +539,7 @@ t1 CREATE TABLE `t1` (
`substring(_latin2'ab',1)` char(2) character set latin2 NOT NULL default '', `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 '', `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 '' `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; drop table t1;
select SUBSTR('abcdefg',3,2); select SUBSTR('abcdefg',3,2);
SUBSTR('abcdefg',3,2) SUBSTR('abcdefg',3,2)

View File

@ -49,7 +49,7 @@ t1 CREATE TABLE `t1` (
`database()` char(34) character set utf8 NOT NULL default '', `database()` char(34) character set utf8 NOT NULL default '',
`user()` char(77) character set utf8 NOT NULL default '', `user()` char(77) character set utf8 NOT NULL default '',
`version` char(40) default NULL `version` char(40) default NULL
) TYPE=MyISAM CHARSET=latin1 ) TYPE=MyISAM DEFAULT CHARSET=latin1
drop table t1; drop table t1;
select TRUE,FALSE,NULL; select TRUE,FALSE,NULL;
TRUE FALSE NULL TRUE FALSE NULL

View File

@ -11,7 +11,7 @@ t1 CREATE TABLE `t1` (
`g` geometry NOT NULL default '', `g` geometry NOT NULL default '',
PRIMARY KEY (`fid`), PRIMARY KEY (`fid`),
SPATIAL KEY `g` (`g`(32)) 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(150 150, 150 150)'));
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(149 149, 151 151)')); INSERT INTO t1 (g) VALUES (GeomFromText('LineString(149 149, 151 151)'));
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(148 148, 152 152)')); INSERT INTO t1 (g) VALUES (GeomFromText('LineString(148 148, 152 152)'));
@ -294,7 +294,7 @@ t2 CREATE TABLE `t2` (
`g` geometry NOT NULL default '', `g` geometry NOT NULL default '',
PRIMARY KEY (`fid`), PRIMARY KEY (`fid`),
SPATIAL KEY `g` (`g`(32)) SPATIAL KEY `g` (`g`(32))
) TYPE=MyISAM CHARSET=latin1 ) TYPE=MyISAM DEFAULT CHARSET=latin1
SELECT count(*) FROM t2; SELECT count(*) FROM t2;
count(*) count(*)
100 100

View File

@ -819,7 +819,7 @@ Table Create Table
t1 CREATE TABLE `t1` ( t1 CREATE TABLE `t1` (
`a` char(20) default NULL, `a` char(20) default NULL,
KEY `a` (`a`(5)) KEY `a` (`a`(5))
) TYPE=InnoDB CHARSET=latin1 ) TYPE=InnoDB DEFAULT CHARSET=latin1
drop table t1; drop table t1;
create temporary table t1 (a int not null auto_increment, primary key(a)) type=innodb; create temporary table t1 (a int not null auto_increment, primary key(a)) type=innodb;
insert into t1 values (NULL),(NULL),(NULL); insert into t1 values (NULL),(NULL),(NULL);

View File

@ -1,3 +1,4 @@
drop table if exists t1, t2, t3;
SET @save_key_buffer=@@key_buffer_size; SET @save_key_buffer=@@key_buffer_size;
SELECT @@key_buffer_size, @@small.key_buffer_size; SELECT @@key_buffer_size, @@small.key_buffer_size;
@@key_buffer_size @@small.key_buffer_size @@key_buffer_size @@small.key_buffer_size
@ -74,15 +75,15 @@ select @@keycache1.key_buffer_size;
0 0
select @@keycache1.key_cache_block_size; select @@keycache1.key_cache_block_size;
@@keycache1.key_cache_block_size @@keycache1.key_cache_block_size
0 2048
select @@key_buffer_size; select @@key_buffer_size;
@@key_buffer_size @@key_buffer_size
2097152 2097152
select @@key_cache_block_size; select @@key_cache_block_size;
@@key_cache_block_size @@key_cache_block_size
1024 1024
drop table if exists t1, t2; set global keycache1.key_buffer_size=1024*1024;
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)); 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 t1 values (1, 'qqqq'), (11, 'yyyy');
insert into t2 values (1, 1, 'qqqq'), (2, 1, 'pppp'), insert into t2 values (1, 1, 'qqqq'), (2, 1, 'pppp'),
@ -99,7 +100,7 @@ p i a
4 3 zzzz 4 3 zzzz
update t1 set p=2 where p=1; update t1 set p=2 where p=1;
update t2 set i=2 where i=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 Table Op Msg_type Msg_text
test.t1 assign_to_keycache status OK test.t1 assign_to_keycache status OK
explain select p from t1; 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; select count(*) from t1, t2 where t1.p = t2.i;
count(*) count(*)
3 3
cache index t2 keys in keycache1; cache index t2 in keycache1;
Table Op Msg_type Msg_text Table Op Msg_type Msg_text
test.t2 assign_to_keycache status OK test.t2 assign_to_keycache status OK
update t2 set p=p+1000, i=2 where a='qqqq'; 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 Table Op Msg_type Msg_text
test.t2 assign_to_keycache status OK test.t2 assign_to_keycache status OK
insert into t2 values (2000, 3, 'yyyy'); insert into t2 values (2000, 3, 'yyyy');
cache index t2 keys in keycache1; cache index t2 in keycache1;
Table Op Msg_type Msg_text Table Op Msg_type Msg_text
test.t2 assign_to_keycache status OK test.t2 assign_to_keycache status OK
update t2 set p=3000 where a='zzzz'; update t2 set p=3000 where a='zzzz';
@ -174,6 +175,12 @@ qqqq
yyyy yyyy
yyyy yyyy
zzzz 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; select @@keycache2.key_buffer_size;
@@keycache2.key_buffer_size @@keycache2.key_buffer_size
4194304 4194304
@ -186,7 +193,11 @@ select @@keycache2.key_buffer_size;
0 0
select @@keycache2.key_cache_block_size; select @@keycache2.key_cache_block_size;
@@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 t2 set p=4000 where a='zzzz';
update t1 set p=p+1; update t1 set p=p+1;
set global keycache1.key_buffer_size=0; set global keycache1.key_buffer_size=0;
@ -232,3 +243,17 @@ select p from t1;
p p
3 3
12 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;

View File

@ -175,7 +175,7 @@ t3 CREATE TABLE `t3` (
`a` int(11) NOT NULL default '0', `a` int(11) NOT NULL default '0',
`b` char(20) default NULL, `b` char(20) default NULL,
KEY `a` (`a`) 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); create table t4 (a int not null, b char(10), key(a)) type=MERGE UNION=(t1,t2);
select * from t4; select * from t4;
ERROR HY000: Can't open file: 't4.MRG' (errno: 143) 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', `a` int(11) NOT NULL default '0',
`b` char(20) default NULL, `b` char(20) default NULL,
KEY `a` (`a`) 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; alter table t5 type=myisam;
drop table t5, mysqltest.t6; drop table t5, mysqltest.t6;
drop database mysqltest; drop database mysqltest;
@ -263,14 +263,14 @@ t3 CREATE TABLE `t3` (
`incr` int(11) NOT NULL default '0', `incr` int(11) NOT NULL default '0',
`othr` int(11) NOT NULL default '0', `othr` int(11) NOT NULL default '0',
PRIMARY KEY (`incr`) 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; alter table t3 drop primary key;
show create table t3; show create table t3;
Table Create Table Table Create Table
t3 CREATE TABLE `t3` ( t3 CREATE TABLE `t3` (
`incr` int(11) NOT NULL default '0', `incr` int(11) NOT NULL default '0',
`othr` 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; drop table t3,t2,t1;
create table t1 (a int not null, key(a)) type=merge; create table t1 (a int not null, key(a)) type=merge;
select * from t1; select * from t1;
@ -299,28 +299,28 @@ t3 CREATE TABLE `t3` (
`a` int(11) NOT NULL default '0', `a` int(11) NOT NULL default '0',
`b` int(11) NOT NULL default '0', `b` int(11) NOT NULL default '0',
KEY `a` (`a`,`b`) KEY `a` (`a`,`b`)
) TYPE=MyISAM CHARSET=latin1 ) TYPE=MyISAM DEFAULT CHARSET=latin1
show create table t4; show create table t4;
Table Create Table Table Create Table
t4 CREATE TABLE `t4` ( t4 CREATE TABLE `t4` (
`a` int(11) NOT NULL default '0', `a` int(11) NOT NULL default '0',
`b` int(11) NOT NULL default '0', `b` int(11) NOT NULL default '0',
KEY `a` (`a`,`b`) 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; show create table t5;
Table Create Table Table Create Table
t5 CREATE TABLE `t5` ( t5 CREATE TABLE `t5` (
`a` int(11) NOT NULL default '0', `a` int(11) NOT NULL default '0',
`b` int(11) NOT NULL auto_increment, `b` int(11) NOT NULL auto_increment,
PRIMARY KEY (`a`,`b`) 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; show create table t6;
Table Create Table Table Create Table
t6 CREATE TABLE `t6` ( t6 CREATE TABLE `t6` (
`a` int(11) NOT NULL default '0', `a` int(11) NOT NULL default '0',
`b` int(11) NOT NULL auto_increment, `b` int(11) NOT NULL auto_increment,
PRIMARY KEY (`a`,`b`) 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 t1 values (1,NULL),(1,NULL),(1,NULL),(1,NULL);
insert into t2 values (2,NULL),(2,NULL),(2,NULL),(2,NULL); insert into t2 values (2,NULL),(2,NULL),(2,NULL),(2,NULL);
select * from t3 order by b,a limit 3; select * from t3 order by b,a limit 3;
@ -385,7 +385,7 @@ t4 CREATE TABLE `t4` (
`a` int(11) NOT NULL default '0', `a` int(11) NOT NULL default '0',
`b` int(11) NOT NULL default '0', `b` int(11) NOT NULL default '0',
KEY `a` (`a`,`b`) 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; select * from t4 order by a,b;
a b a b
1 1 1 1
@ -411,7 +411,7 @@ t4 CREATE TABLE `t4` (
`a` int(11) NOT NULL default '0', `a` int(11) NOT NULL default '0',
`b` int(11) NOT NULL default '0', `b` int(11) NOT NULL default '0',
KEY `a` (`a`,`b`) 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); insert into t4 values (4,1),(4,2);
select * from t1 order by a,b; select * from t1 order by a,b;
a b a b

View File

@ -69,7 +69,7 @@ flush status;
select @@preload_buffer_size; select @@preload_buffer_size;
@@preload_buffer_size @@preload_buffer_size
32768 32768
load index into cache t1 keys; load index into cache t1;
Table Op Msg_type Msg_text Table Op Msg_type Msg_text
test.t1 preload_keys status OK test.t1 preload_keys status OK
show status like "key_read%"; show status like "key_read%";
@ -93,7 +93,7 @@ set session preload_buffer_size=256*1024;
select @@preload_buffer_size; select @@preload_buffer_size;
@@preload_buffer_size @@preload_buffer_size
262144 262144
load index into cache t1 keys ignore leaves; load index into cache t1 ignore leaves;
Table Op Msg_type Msg_text Table Op Msg_type Msg_text
test.t1 preload_keys status OK test.t1 preload_keys status OK
show status like "key_read%"; show status like "key_read%";
@ -117,7 +117,7 @@ set session preload_buffer_size=1*1024;
select @@preload_buffer_size; select @@preload_buffer_size;
@@preload_buffer_size @@preload_buffer_size
1024 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 Table Op Msg_type Msg_text
test.t1 preload_keys status OK test.t1 preload_keys status OK
test.t2 preload_keys status OK test.t2 preload_keys status OK
@ -141,7 +141,7 @@ show status like "key_read%";
Variable_name Value Variable_name Value
Key_read_requests 0 Key_read_requests 0
Key_reads 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 Table Op Msg_type Msg_text
test.t3 preload_keys error Table 'test.t3' doesn't exist test.t3 preload_keys error Table 'test.t3' doesn't exist
test.t2 preload_keys status OK test.t2 preload_keys status OK

View File

@ -77,13 +77,13 @@ show create table t1;
Table Create Table Table Create Table
t1 CREATE TEMPORARY TABLE `t1` ( t1 CREATE TEMPORARY TABLE `t1` (
`a` int(11) NOT NULL default '0' `a` int(11) NOT NULL default '0'
) TYPE=MyISAM CHARSET=latin1 ) TYPE=MyISAM DEFAULT CHARSET=latin1
alter table t1 rename t2; alter table t1 rename t2;
show create table t2; show create table t2;
Table Create Table Table Create Table
t2 CREATE TEMPORARY TABLE `t2` ( t2 CREATE TEMPORARY TABLE `t2` (
`a` int(11) NOT NULL default '0' `a` int(11) NOT NULL default '0'
) TYPE=MyISAM CHARSET=latin1 ) TYPE=MyISAM DEFAULT CHARSET=latin1
drop table t2; drop table t2;
create table t1 ( create table t1 (
test_set set( 'val1', 'val2', 'val3' ) not null default '', 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 '', `test_set` set('val1','val2','val3') NOT NULL default '',
`name` char(20) default 'O''Brien' COMMENT 'O''Brien as default', `name` char(20) default 'O''Brien' COMMENT 'O''Brien as default',
`c` int(11) NOT NULL default '0' COMMENT 'int column' `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; show full columns from t1;
Field Type Collation Null Key Default Extra Privileges Comment Field Type Collation Null Key Default Extra Privileges Comment
test_set set('val1','val2','val3') latin1_swedish_ci select,insert,update,references test_set set('val1','val2','val3') latin1_swedish_ci select,insert,update,references
@ -109,7 +109,7 @@ Table Create Table
t1 CREATE TABLE `t1` ( t1 CREATE TABLE `t1` (
`a` int(11) NOT NULL default '0', `a` int(11) NOT NULL default '0',
UNIQUE KEY `aa` (`a`) UNIQUE KEY `aa` (`a`)
) TYPE=MyISAM CHARSET=latin1 ) TYPE=MyISAM DEFAULT CHARSET=latin1
drop table t1; drop table t1;
create table t1 (a int not null, primary key (a)); create table t1 (a int not null, primary key (a));
show create table t1; show create table t1;
@ -117,7 +117,7 @@ Table Create Table
t1 CREATE TABLE `t1` ( t1 CREATE TABLE `t1` (
`a` int(11) NOT NULL default '0', `a` int(11) NOT NULL default '0',
PRIMARY KEY (`a`) PRIMARY KEY (`a`)
) TYPE=MyISAM CHARSET=latin1 ) TYPE=MyISAM DEFAULT CHARSET=latin1
drop table t1; drop table t1;
flush tables; flush tables;
show open tables; show open tables;
@ -135,7 +135,7 @@ t1 CREATE TABLE `t1` (
`a` int(11) NOT NULL default '0', `a` int(11) NOT NULL default '0',
`b` char(10) default NULL, `b` char(10) default NULL,
KEY `b` (`b`) 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; alter table t1 MAX_ROWS=200 ROW_FORMAT=dynamic PACK_KEYS=0;
show create table t1; show create table t1;
Table Create Table Table Create Table
@ -143,7 +143,7 @@ t1 CREATE TABLE `t1` (
`a` int(11) NOT NULL default '0', `a` int(11) NOT NULL default '0',
`b` varchar(10) default NULL, `b` varchar(10) default NULL,
KEY `b` (`b`) 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; 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; show create table t1;
Table Create Table Table Create Table
@ -151,7 +151,7 @@ t1 CREATE TABLE `t1` (
`a` int(11) NOT NULL default '0', `a` int(11) NOT NULL default '0',
`b` varchar(10) default NULL, `b` varchar(10) default NULL,
KEY `b` (`b`) KEY `b` (`b`)
) TYPE=MyISAM CHARSET=latin1 ) TYPE=MyISAM DEFAULT CHARSET=latin1
drop table t1; 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)); 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; show columns from t1;
@ -221,7 +221,7 @@ t1 CREATE TABLE `t1` (
`type_long_blob` longblob, `type_long_blob` longblob,
PRIMARY KEY (`type_tiny`), PRIMARY KEY (`type_tiny`),
KEY `type_short` (`type_short`) 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"); insert into t1 (type_timestamp) values ("2003-02-07 10:00:01");
select * from t1; 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 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

View File

@ -18,7 +18,7 @@ t1 CREATE TABLE `t1` (
`email` varchar(60) character set latin2 NOT NULL default '', `email` varchar(60) character set latin2 NOT NULL default '',
PRIMARY KEY (`a`), PRIMARY KEY (`a`),
UNIQUE KEY `email` TYPE BTREE (`email`) 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"; set @@sql_mode="ansi_quotes";
show variables like 'sql_mode'; show variables like 'sql_mode';
Variable_name Value Variable_name Value
@ -31,7 +31,7 @@ t1 CREATE TABLE "t1" (
"email" varchar(60) character set latin2 NOT NULL default '', "email" varchar(60) character set latin2 NOT NULL default '',
PRIMARY KEY ("a"), PRIMARY KEY ("a"),
UNIQUE KEY "email" TYPE BTREE ("email") 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"; set @@sql_mode="no_table_options";
show variables like 'sql_mode'; show variables like 'sql_mode';
Variable_name Value Variable_name Value
@ -57,7 +57,7 @@ t1 CREATE TABLE `t1` (
`email` varchar(60) character set latin2 NOT NULL default '', `email` varchar(60) character set latin2 NOT NULL default '',
PRIMARY KEY (`a`), PRIMARY KEY (`a`),
UNIQUE KEY `email` (`email`) 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"; set @@sql_mode="no_field_options,mysql323,mysql40";
show variables like 'sql_mode'; show variables like 'sql_mode';
Variable_name Value Variable_name Value

View File

@ -1071,7 +1071,7 @@ Table Create Table
t1 CREATE TABLE `t1` ( t1 CREATE TABLE `t1` (
`a` bigint(1) NOT NULL default '0', `a` bigint(1) NOT NULL default '0',
`(SELECT 1)` 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; drop table t1;
CREATE TABLE t1 SELECT * FROM (SELECT 1 as a,(SELECT a)) a; CREATE TABLE t1 SELECT * FROM (SELECT 1 as a,(SELECT a)) a;
SHOW CREATE TABLE t1; SHOW CREATE TABLE t1;
@ -1079,7 +1079,7 @@ Table Create Table
t1 CREATE TABLE `t1` ( t1 CREATE TABLE `t1` (
`a` bigint(1) NOT NULL default '0', `a` bigint(1) NOT NULL default '0',
`(SELECT 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; drop table t1;
CREATE TABLE t1 SELECT * FROM (SELECT 1 as a,(SELECT a+0)) a; CREATE TABLE t1 SELECT * FROM (SELECT 1 as a,(SELECT a+0)) a;
SHOW CREATE TABLE t1; SHOW CREATE TABLE t1;
@ -1087,7 +1087,7 @@ Table Create Table
t1 CREATE TABLE `t1` ( t1 CREATE TABLE `t1` (
`a` bigint(1) NOT NULL default '0', `a` bigint(1) NOT NULL default '0',
`(SELECT a+0)` bigint(17) 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; drop table t1;
CREATE TABLE t1 SELECT (SELECT 1 as a UNION SELECT 1+1 limit 1,1) as a; CREATE TABLE t1 SELECT (SELECT 1 as a UNION SELECT 1+1 limit 1,1) as a;
select * from t1; select * from t1;
@ -1097,7 +1097,7 @@ SHOW CREATE TABLE t1;
Table Create Table Table Create Table
t1 CREATE TABLE `t1` ( t1 CREATE TABLE `t1` (
`a` bigint(17) NOT NULL default '0' `a` bigint(17) NOT NULL default '0'
) TYPE=MyISAM CHARSET=latin1 ) TYPE=MyISAM DEFAULT CHARSET=latin1
drop table t1; drop table t1;
create table t1 (a int); create table t1 (a int);
insert into t1 values (1), (2), (3); insert into t1 values (1), (2), (3);

View File

@ -23,7 +23,7 @@ Table Create Table
t3 CREATE TABLE `t3` ( t3 CREATE TABLE `t3` (
`a` mediumtext, `a` mediumtext,
`b` mediumblob `b` mediumblob
) TYPE=MyISAM CHARSET=latin1 ) TYPE=MyISAM DEFAULT CHARSET=latin1
drop table t1,t2,t3 drop table t1,t2,t3
#; #;
CREATE TABLE t1 (a char(257) default "hello"); CREATE TABLE t1 (a char(257) default "hello");

View File

@ -1627,12 +1627,12 @@ show create table t1;
Table Create Table Table Create Table
t1 CREATE TABLE `t1` ( t1 CREATE TABLE `t1` (
`a` enum('','a','b') NOT NULL default '' `a` enum('','a','b') NOT NULL default ''
) TYPE=MyISAM CHARSET=latin1 ) TYPE=MyISAM DEFAULT CHARSET=latin1
drop table t1; drop table t1;
create table t1 (a enum (' ','a','b ') not null default 'b '); create table t1 (a enum (' ','a','b ') not null default 'b ');
show create table t1; show create table t1;
Table Create Table Table Create Table
t1 CREATE TABLE `t1` ( t1 CREATE TABLE `t1` (
`a` enum('','a','b') NOT NULL default 'b' `a` enum('','a','b') NOT NULL default 'b'
) TYPE=MyISAM CHARSET=latin1 ) TYPE=MyISAM DEFAULT CHARSET=latin1
drop table t1; drop table t1;

View File

@ -4,47 +4,47 @@ show create table t1;
Table Create Table Table Create Table
t1 CREATE TABLE `t1` ( t1 CREATE TABLE `t1` (
`c` char(10) character set utf8 default NULL `c` char(10) character set utf8 default NULL
) TYPE=MyISAM CHARSET=latin1 ) TYPE=MyISAM DEFAULT CHARSET=latin1
drop table t1; drop table t1;
create table t1 (c national char(10)); create table t1 (c national char(10));
show create table t1; show create table t1;
Table Create Table Table Create Table
t1 CREATE TABLE `t1` ( t1 CREATE TABLE `t1` (
`c` char(10) character set utf8 default NULL `c` char(10) character set utf8 default NULL
) TYPE=MyISAM CHARSET=latin1 ) TYPE=MyISAM DEFAULT CHARSET=latin1
drop table t1; drop table t1;
create table t1 (c national varchar(10)); create table t1 (c national varchar(10));
show create table t1; show create table t1;
Table Create Table Table Create Table
t1 CREATE TABLE `t1` ( t1 CREATE TABLE `t1` (
`c` varchar(10) character set utf8 default NULL `c` varchar(10) character set utf8 default NULL
) TYPE=MyISAM CHARSET=latin1 ) TYPE=MyISAM DEFAULT CHARSET=latin1
drop table t1; drop table t1;
create table t1 (c nvarchar(10)); create table t1 (c nvarchar(10));
show create table t1; show create table t1;
Table Create Table Table Create Table
t1 CREATE TABLE `t1` ( t1 CREATE TABLE `t1` (
`c` varchar(10) character set utf8 default NULL `c` varchar(10) character set utf8 default NULL
) TYPE=MyISAM CHARSET=latin1 ) TYPE=MyISAM DEFAULT CHARSET=latin1
drop table t1; drop table t1;
create table t1 (c nchar varchar(10)); create table t1 (c nchar varchar(10));
show create table t1; show create table t1;
Table Create Table Table Create Table
t1 CREATE TABLE `t1` ( t1 CREATE TABLE `t1` (
`c` varchar(10) character set utf8 default NULL `c` varchar(10) character set utf8 default NULL
) TYPE=MyISAM CHARSET=latin1 ) TYPE=MyISAM DEFAULT CHARSET=latin1
drop table t1; drop table t1;
create table t1 (c national character varying(10)); create table t1 (c national character varying(10));
show create table t1; show create table t1;
Table Create Table Table Create Table
t1 CREATE TABLE `t1` ( t1 CREATE TABLE `t1` (
`c` varchar(10) character set utf8 default NULL `c` varchar(10) character set utf8 default NULL
) TYPE=MyISAM CHARSET=latin1 ) TYPE=MyISAM DEFAULT CHARSET=latin1
drop table t1; drop table t1;
create table t1 (c nchar varying(10)); create table t1 (c nchar varying(10));
show create table t1; show create table t1;
Table Create Table Table Create Table
t1 CREATE TABLE `t1` ( t1 CREATE TABLE `t1` (
`c` varchar(10) character set utf8 default NULL `c` varchar(10) character set utf8 default NULL
) TYPE=MyISAM CHARSET=latin1 ) TYPE=MyISAM DEFAULT CHARSET=latin1
drop table t1; drop table t1;

View File

@ -4,14 +4,14 @@ show create table t1;
Table Create Table Table Create Table
t1 CREATE TABLE `t1` ( t1 CREATE TABLE `t1` (
`a` set('','a','b') NOT NULL default '' `a` set('','a','b') NOT NULL default ''
) TYPE=MyISAM CHARSET=latin1 ) TYPE=MyISAM DEFAULT CHARSET=latin1
drop table t1; drop table t1;
create table t1 (a set (' ','a','b ') not null default 'b '); create table t1 (a set (' ','a','b ') not null default 'b ');
show create table t1; show create table t1;
Table Create Table Table Create Table
t1 CREATE TABLE `t1` ( t1 CREATE TABLE `t1` (
`a` set('','a','b') NOT NULL default 'b' `a` set('','a','b') NOT NULL default 'b'
) TYPE=MyISAM CHARSET=latin1 ) TYPE=MyISAM DEFAULT CHARSET=latin1
drop table t1; 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; 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; DROP TABLE t1;

View File

@ -486,7 +486,7 @@ a b
2 2 2 2
3 3 3 3
4 4 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 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 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 2 UNION t1 index PRIMARY PRIMARY 4 NULL 4 Using index

View File

@ -170,6 +170,17 @@ select a,hex(a) from t1;
alter table t1 change a a char(10) character set koi8r; alter table t1 change a a char(10) character set koi8r;
select a,hex(a) from t1; 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; drop table t1;
# #

View File

@ -16,7 +16,7 @@ ALTER TABLE t1 CHANGE comment comment CHAR(32) CHARACTER SET latin2 NOT NULL;
SHOW CREATE TABLE t1; SHOW CREATE TABLE t1;
ALTER TABLE t1 ADD latin5_f CHAR(32) NOT NULL; ALTER TABLE t1 ADD latin5_f CHAR(32) NOT NULL;
SHOW CREATE TABLE t1; 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; ALTER TABLE t1 ADD latin2_f CHAR(32) NOT NULL;
SHOW CREATE TABLE t1; SHOW CREATE TABLE t1;
ALTER TABLE t1 DROP latin2_f, DROP latin5_f; ALTER TABLE t1 DROP latin2_f, DROP latin5_f;

View File

@ -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 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); 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;
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;
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;
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;
drop table t1,t2; drop table t1,t2;
# #

View File

@ -12,12 +12,14 @@ create table t1 (a tinyint not null auto_increment, b blob not null, primary key
let $1=100; let $1=100;
disable_query_log; disable_query_log;
--disable_warnings
while ($1) while ($1)
{ {
eval insert into t1 (b) values(repeat(char(65+$1),65540-$1)); eval insert into t1 (b) values(repeat(char(65+$1),65540-$1));
dec $1; dec $1;
} }
enable_query_log; enable_query_log;
--enable_warnings
delete from t1 where (a & 1); delete from t1 where (a & 1);
select sum(length(b)) from t1; select sum(length(b)) from t1;
drop table t1; drop table t1;

View File

@ -112,7 +112,7 @@ drop table t1, t2;
create table t1 (a int primary key); create table t1 (a int primary key);
insert into t1 values(1),(2); 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); 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 --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); 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; drop table t1;

View File

@ -1,6 +1,9 @@
# #
# Test of multiple key caches # Test of multiple key caches
# #
--disable_warnings
drop table if exists t1, t2, t3;
--enable_warnings
SET @save_key_buffer=@@key_buffer_size; SET @save_key_buffer=@@key_buffer_size;
@ -58,12 +61,9 @@ select @@keycache1.key_cache_block_size;
select @@key_buffer_size; select @@key_buffer_size;
select @@key_cache_block_size; select @@key_cache_block_size;
set global keycache1.key_buffer_size=1024*1024;
--disable_warnings create table t1 (p int primary key, a char(10)) delay_key_write=1;
drop table if exists t1, t2;
--enable_warnings
create table t1 (p int primary key, a char(10));
create table t2 (p int primary key, i int, a char(10), key k1(i), key k2(a)); 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 t1 values (1, 'qqqq'), (11, 'yyyy');
@ -75,7 +75,7 @@ select * from t2;
update t1 set p=2 where p=1; update t1 set p=2 where p=1;
update t2 set i=2 where i=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; explain select p from t1;
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; explain select count(*) from t1, t2 where t1.p = t2.i;
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'; 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'); 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'; update t2 set p=3000 where a='zzzz';
select * from t2; select * from t2;
explain select p from t2; explain select p from t2;
@ -98,12 +98,18 @@ select i from t2;
explain select a from t2; explain select a from t2;
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_buffer_size;
select @@keycache2.key_cache_block_size; select @@keycache2.key_cache_block_size;
set global keycache2.key_buffer_size=0; set global keycache2.key_buffer_size=0;
select @@keycache2.key_buffer_size; select @@keycache2.key_buffer_size;
select @@keycache2.key_cache_block_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 t2 set p=4000 where a='zzzz';
update t1 set p=p+1; update t1 set p=p+1;
@ -119,4 +125,14 @@ select a from t2;
select * from t1; select * from t1;
select p 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;

View File

@ -63,7 +63,7 @@ show status like "key_read%";
flush tables; flush status; flush tables; flush status;
select @@preload_buffer_size; select @@preload_buffer_size;
load index into cache t1 keys; load index into cache t1;
show status like "key_read%"; show status like "key_read%";
select count(*) from t1 where b = 'test1'; select count(*) from t1 where b = 'test1';
show status like "key_read%"; show status like "key_read%";
@ -72,7 +72,7 @@ flush tables; flush status;
show status like "key_read%"; show status like "key_read%";
set session preload_buffer_size=256*1024; set session preload_buffer_size=256*1024;
select @@preload_buffer_size; select @@preload_buffer_size;
load index into cache t1 keys ignore leaves; load index into cache t1 ignore leaves;
show status like "key_read%"; show status like "key_read%";
select count(*) from t1 where b = 'test1'; select count(*) from t1 where b = 'test1';
show status like "key_read%"; show status like "key_read%";
@ -81,7 +81,7 @@ flush tables; flush status;
show status like "key_read%"; show status like "key_read%";
set session preload_buffer_size=1*1024; set session preload_buffer_size=1*1024;
select @@preload_buffer_size; 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%"; show status like "key_read%";
select count(*) from t1 where b = 'test1'; select count(*) from t1 where b = 'test1';
select count(*) from t2 where b = 'test1'; select count(*) from t2 where b = 'test1';
@ -89,7 +89,7 @@ show status like "key_read%";
flush tables; flush status; flush tables; flush status;
show status like "key_read%"; 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%"; show status like "key_read%";
flush tables; flush status; flush tables; flush status;

View File

@ -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 * 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 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); (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); explain (select * from t1 where a=1) union (select * from t1 where b=1);
drop table t1,t2; drop table t1,t2;
create table t1 ( id int not null auto_increment, primary key (id) ,user_name text ); create table t1 ( id int not null auto_increment, primary key (id) ,user_name text );

View File

@ -29,7 +29,7 @@ libmysys_a_SOURCES = my_init.c my_getwd.c mf_getdate.c\
mf_path.c mf_loadpath.c\ mf_path.c mf_loadpath.c\
my_open.c my_create.c my_dup.c my_seek.c my_read.c \ my_open.c my_create.c my_dup.c my_seek.c my_read.c \
my_pread.c my_write.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_iocache.c mf_iocache2.c mf_cache.c mf_tempfile.c \
mf_tempdir.c my_lock.c mf_brkhant.c my_alarm.c \ mf_tempdir.c my_lock.c mf_brkhant.c my_alarm.c \
my_malloc.c my_realloc.c my_once.c mulalloc.c \ my_malloc.c my_realloc.c my_once.c mulalloc.c \

View File

@ -53,7 +53,7 @@ _hash_init(HASH *hash,CHARSET_INFO *charset,
if (my_init_dynamic_array_ci(&hash->array,sizeof(HASH_LINK),size,0)) if (my_init_dynamic_array_ci(&hash->array,sizeof(HASH_LINK),size,0))
{ {
hash->free=0; /* Allow call to hash_free */ hash->free=0; /* Allow call to hash_free */
DBUG_RETURN(TRUE); DBUG_RETURN(1);
} }
hash->key_offset=key_offset; hash->key_offset=key_offset;
hash->key_length=key_length; hash->key_length=key_length;

View File

@ -142,7 +142,7 @@ typedef struct st_block_link
KEY_CACHE_VAR dflt_key_cache_var= 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; 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 */ ulong warm_blocks; /* number of blocks in warm sub-chain */
#if defined(KEYCACHE_DEBUG) #if defined(KEYCACHE_DEBUG)
long blocks_available; /* number of blocks available in the LRU chain */ 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_root; /* arr. of entries into hash table buckets */
HASH_LINK *hash_link_root; /* memory for hash table links */ HASH_LINK *hash_link_root; /* memory for hash table links */
HASH_LINK *free_hash_list; /* list of free hash links */ HASH_LINK *free_hash_list; /* list of free hash links */
@ -184,7 +184,7 @@ typedef struct st_key_cache
} KEY_CACHE; } KEY_CACHE;
static int flush_all_key_blocks(KEY_CACHE_HANDLE keycache); 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); const char *where, my_bool lock);
#define KEYCACHE_HASH(f, pos) \ #define KEYCACHE_HASH(f, pos) \
@ -284,7 +284,7 @@ static uint next_power(uint value)
SYNOPSIS SYNOPSIS
init_ky_cache() init_ky_cache()
pkeycache in/out pointer to the key cache handle 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 use_mem total memory to use for the key cache
env ref to other parameters of the key cache, if any 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. handle for a key cache with new blocks.
It's assumed that no two threads call this function simultaneously It's assumed that no two threads call this function simultaneously
referring to the same key cache handle. referring to the same key cache handle.
*/ */
int init_key_cache(KEY_CACHE_HANDLE *pkeycache, uint key_cache_block_size, 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; uint blocks, hash_links, length;
int error; int error;
KEY_CACHE *keycache; KEY_CACHE *keycache;
DBUG_ENTER("init_key_cache"); DBUG_ENTER("init_key_cache");
DBUG_ASSERT(key_cache_block_size >= 512);
if (!(keycache= (KEY_CACHE *) *pkeycache) && if (!(keycache= (KEY_CACHE *) *pkeycache) &&
!(keycache= (KEY_CACHE *) my_malloc(sizeof(KEY_CACHE), !(keycache= (KEY_CACHE *) my_malloc(sizeof(KEY_CACHE),
MYF(MY_ZEROFILL)))) MYF(MY_ZEROFILL))))
DBUG_RETURN(0); DBUG_RETURN(0);
keycache->env= env; keycache->env= env;
KEYCACHE_DEBUG_OPEN; 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) if (! keycache->key_cache_inited)
{ {
keycache->key_cache_inited= TRUE; keycache->key_cache_inited= 1;
keycache->disk_blocks= -1; keycache->disk_blocks= -1;
pthread_mutex_init(&keycache->cache_lock, MY_MUTEX_INIT_FAST); pthread_mutex_init(&keycache->cache_lock, MY_MUTEX_INIT_FAST);
keycache->key_cache_shift= my_bit_log2(key_cache_block_size); keycache->key_cache_shift= my_bit_log2(key_cache_block_size);
keycache->key_cache_mem_size= use_mem; keycache->key_cache_mem_size= use_mem;
keycache->key_cache_block_size= key_cache_block_size; keycache->key_cache_block_size= key_cache_block_size;
DBUG_PRINT("info", ("key_cache_block_size: %u", 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 These are safety deallocations: actually we always call the
function after having called end_key_cache that deallocates function after having called end_key_cache that deallocates
these memory itself. these memory itself.
*/ */
if (keycache->block_mem) 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; keycache->block_mem= NULL;
if (keycache->block_root) if (keycache->block_root)
my_free((gptr) keycache->block_root, MYF(0)); my_free((gptr) keycache->block_root, MYF(0));
keycache->block_root= NULL; keycache->block_root= NULL;
blocks= (uint) (use_mem / (sizeof(BLOCK_LINK) + 2 * sizeof(HASH_LINK) + 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) */ /* It doesn't make sense to have too few blocks (less than 8) */
if (blocks >= 8 && keycache->disk_blocks < 0) 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 #endif
while ((length= (ALIGN_SIZE(blocks * sizeof(BLOCK_LINK)) + while ((length= (ALIGN_SIZE(blocks * sizeof(BLOCK_LINK)) +
ALIGN_SIZE(hash_links * sizeof(HASH_LINK)) + ALIGN_SIZE(hash_links * sizeof(HASH_LINK)) +
ALIGN_SIZE(sizeof(HASH_LINK*) * ALIGN_SIZE(sizeof(HASH_LINK*) *
keycache->hash_entries))) + keycache->hash_entries))) +
((ulong) blocks << keycache->key_cache_shift) > use_mem) ((ulong) blocks << keycache->key_cache_shift) > use_mem)
blocks--; blocks--;
/* Allocate memory for cache page buffers */ /* Allocate memory for cache page buffers */
if ((keycache->block_mem= if ((keycache->block_mem=
my_malloc_lock((ulong) blocks * keycache->key_cache_block_size, my_malloc_lock((ulong) blocks * keycache->key_cache_block_size,
MYF(0)))) MYF(0))))
{ {
/* /*
Allocate memory for blocks, hash_links and hash entries; Allocate memory for blocks, hash_links and hash entries;
For each block 2 hash links are allocated For each block 2 hash links are allocated
*/ */
if ((keycache->block_root= (BLOCK_LINK*) my_malloc((uint) length, if ((keycache->block_root= (BLOCK_LINK*) my_malloc((uint) length,
MYF(0)))) 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))); ALIGN_SIZE(blocks*sizeof(BLOCK_LINK)));
keycache->hash_link_root= (HASH_LINK*) ((char*) keycache->hash_root + keycache->hash_link_root= (HASH_LINK*) ((char*) keycache->hash_root +
ALIGN_SIZE((sizeof(HASH_LINK*) * ALIGN_SIZE((sizeof(HASH_LINK*) *
keycache->hash_entries))); keycache->hash_entries)));
bzero((byte*) keycache->block_root, bzero((byte*) keycache->block_root,
keycache->disk_blocks * sizeof(BLOCK_LINK)); keycache->disk_blocks * sizeof(BLOCK_LINK));
bzero((byte*) keycache->hash_root, bzero((byte*) keycache->hash_root,
keycache->hash_entries * sizeof(HASH_LINK*)); keycache->hash_entries * sizeof(HASH_LINK*));
bzero((byte*) keycache->hash_link_root, bzero((byte*) keycache->hash_link_root,
keycache->hash_links * sizeof(HASH_LINK)); keycache->hash_links * sizeof(HASH_LINK));
keycache->hash_links_used= 0; keycache->hash_links_used= 0;
keycache->free_hash_list= NULL; keycache->free_hash_list= NULL;
keycache->blocks_used= keycache->blocks_changed= 0; 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->used_ins= NULL;
keycache->keycache_time= 0; keycache->keycache_time= 0;
keycache->warm_blocks= 0; keycache->warm_blocks= 0;
keycache->min_warm_blocks= env && env->division_limit ? keycache->min_warm_blocks= (env && env->division_limit ?
blocks * env->division_limit / 100 + 1 : blocks * env->division_limit / 100 + 1 :
blocks; blocks);
keycache->age_threshold= env && env->age_threshold ? keycache->age_threshold= (env && env->age_threshold ?
blocks * env->age_threshold / 100 : blocks * env->age_threshold / 100 :
blocks; blocks);
keycache->waiting_for_hash_link.last_thread= NULL; keycache->waiting_for_hash_link.last_thread= NULL;
keycache->waiting_for_block.last_thread= NULL; keycache->waiting_for_block.last_thread= NULL;
DBUG_PRINT("exit", 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", hash_links: %d hash_link_root %lx",
keycache->disk_blocks, keycache->block_root, keycache->disk_blocks, keycache->block_root,
keycache->hash_entries, keycache->hash_root, keycache->hash_entries, keycache->hash_root,
keycache->hash_links, keycache->hash_link_root)); keycache->hash_links, keycache->hash_link_root));
} }
bzero((gptr) keycache->changed_blocks, bzero((gptr) keycache->changed_blocks,
sizeof(keycache->changed_blocks[0]) * CHANGED_BLOCKS_HASH); 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) if (env)
env->blocks= keycache->disk_blocks > 0 ? keycache->disk_blocks : 0; 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); DBUG_RETURN((int) blocks);
err: err:
@ -473,8 +474,8 @@ err:
SYNOPSIS SYNOPSIS
resize_key_cache() resize_key_cache()
pkeycache in/out pointer to the key cache handle 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 new key cache use_mem total memory to use for the new key cache
RETURN VALUE RETURN VALUE
@ -485,8 +486,8 @@ err:
The function first compares the memory size and the block size parameters The function first compares the memory size and the block size parameters
with the corresponding parameters of the key cache referred by with the corresponding parameters of the key cache referred by
*pkeycache. If they differ the function free the the memory allocated *pkeycache. If they differ the function free the the memory allocated
for the old key cache blocks by calling the end_key_cache function 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. 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, 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; int blocks;
KEY_CACHE *keycache= *pkeycache; KEY_CACHE *keycache= *pkeycache;
DBUG_ENTER("resize_key_cache");
if (key_cache_block_size == keycache->key_cache_block_size && if (key_cache_block_size == keycache->key_cache_block_size &&
use_mem == keycache->key_cache_mem_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; return 0;
} }
keycache_pthread_mutex_unlock(&keycache->cache_lock); 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 */ /* the following will work even if memory is 0 */
blocks=init_key_cache(pkeycache, key_cache_block_size, use_mem, blocks= init_key_cache(pkeycache, key_cache_block_size, use_mem,
keycache->env); keycache->env);
return blocks; return blocks;
} }
/* /*
Change the key cache parameters Change the key cache parameters
SYNOPSIS SYNOPSIS
change_key_cache_param() change_key_cache_param()
keycache the key cache handle keycache the key cache handle
RETURN VALUE RETURN VALUE
none none
@ -537,14 +539,15 @@ void change_key_cache_param(KEY_CACHE_HANDLE keycache)
KEY_CACHE_VAR *env= keycache->env; KEY_CACHE_VAR *env= keycache->env;
DBUG_ENTER("change_key_cache_param"); DBUG_ENTER("change_key_cache_param");
if (!env) if (env)
return; {
if (env->division_limit) if (env->division_limit)
keycache->min_warm_blocks= keycache->disk_blocks * keycache->min_warm_blocks= (keycache->disk_blocks *
env->division_limit / 100 + 1; env->division_limit / 100 + 1);
if (env->age_threshold) if (env->age_threshold)
keycache->age_threshold= keycache->disk_blocks * keycache->age_threshold= (keycache->disk_blocks *
env->age_threshold / 100; env->age_threshold / 100);
}
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
@ -554,7 +557,7 @@ void change_key_cache_param(KEY_CACHE_HANDLE keycache)
SYNOPSIS SYNOPSIS
end_key_cache() 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 cleanup <-> the key cache data structure is freed as well
RETURN VALUE RETURN VALUE
@ -562,15 +565,18 @@ void change_key_cache_param(KEY_CACHE_HANDLE keycache)
NOTES. NOTES.
If the cleanup parameter is TRUE the data structure with all associated If the cleanup parameter is TRUE the data structure with all associated
elements are freed completely and NULL is assigned to *pkeycache. elements are freed completely
Otherwise only memory used by the key cache blocks is freed. 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;;
KEY_CACHE_VAR *env= keycache->env;
DBUG_ENTER("end_key_cache"); DBUG_ENTER("end_key_cache");
DBUG_PRINT("enter", ("key_cache: %lx", keycache));
if (!keycache)
DBUG_VOID_RETURN;
if (keycache->disk_blocks > 0) if (keycache->disk_blocks > 0)
{ {
if (keycache->block_mem) if (keycache->block_mem)
@ -584,18 +590,19 @@ void end_key_cache(KEY_CACHE_HANDLE *pkeycache, my_bool cleanup)
} }
KEYCACHE_DEBUG_CLOSE; KEYCACHE_DEBUG_CLOSE;
keycache->key_cache_inited= 0; keycache->key_cache_inited= 0;
if (env) if ((env= keycache->env))
{
DBUG_PRINT("status", DBUG_PRINT("status",
("used: %d changed: %d w_requests: %ld \ ("used: %d changed: %d w_requests: %ld \
writes: %ld r_requests: %ld reads: %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_w_requests, env->cache_write,
env->cache_r_requests, env->cache_read)); env->cache_r_requests, env->cache_read));
}
if (cleanup) if (cleanup)
{ {
pthread_mutex_destroy(&keycache->cache_lock); pthread_mutex_destroy(&keycache->cache_lock);
my_free((gptr) *pkeycache, MYF(0)); my_free((gptr) keycache, MYF(0));
*pkeycache= NULL;
} }
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} /* end_key_cache */ } /* end_key_cache */
@ -606,8 +613,8 @@ void end_key_cache(KEY_CACHE_HANDLE *pkeycache, my_bool cleanup)
SYNOPSIS SYNOPSIS
link_into_queue() link_into_queue()
wqueue pointer to the queue structure wqueue pointer to the queue structure
thread pointer to the thread to be added to the queue thread pointer to the thread to be added to the queue
RETURN VALUE RETURN VALUE
none none
@ -643,8 +650,8 @@ static inline void link_into_queue(KEYCACHE_WQUEUE *wqueue,
SYNOPSIS SYNOPSIS
unlink_from_queue() unlink_from_queue()
wqueue pointer to the queue structure wqueue pointer to the queue structure
thread pointer to the thread to be removed from the queue thread pointer to the thread to be removed from the queue
RETURN VALUE RETURN VALUE
none none
@ -677,8 +684,8 @@ static inline void unlink_from_queue(KEYCACHE_WQUEUE *wqueue,
SYNOPSIS SYNOPSIS
add_to_queue() add_to_queue()
wqueue pointer to the queue structure wqueue pointer to the queue structure
thread pointer to the thread to be added to the queue thread pointer to the thread to be added to the queue
RETURN VALUE RETURN VALUE
none none
@ -709,8 +716,8 @@ static inline void add_to_queue(KEYCACHE_WQUEUE *wqueue,
SYNOPSIS SYNOPSIS
realease_queue() realease_queue()
wqueue pointer to the queue structure wqueue pointer to the queue structure
thread pointer to the thread to be added to the queue thread pointer to the thread to be added to the queue
RETURN VALUE RETURN VALUE
none none
@ -718,7 +725,7 @@ static inline void add_to_queue(KEYCACHE_WQUEUE *wqueue,
NOTES. NOTES.
See notes for add_to_queue See notes for add_to_queue
When removed from the queue each thread is signaled via condition When removed from the queue each thread is signaled via condition
variable thread->suspend. variable thread->suspend.
*/ */
static void release_queue(KEYCACHE_WQUEUE *wqueue) static void release_queue(KEYCACHE_WQUEUE *wqueue)
@ -809,7 +816,7 @@ static inline void link_to_changed_list(KEY_CACHE *keycache,
SYNOPSIS SYNOPSIS
link_block() 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 block pointer to the block to link to the LRU chain
hot <-> to link the block into the hot subchain hot <-> to link the block into the hot subchain
at_end <-> to link the block at the end of the 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 none
NOTES. NOTES.
The LRU chain is represented by a curcular list of block structures. The LRU chain is represented by a curcular list of block structures.
The list is double-linked of the type (**prev,*next) type. 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 divided into two parts - hot and warm.
There are two pointers to access the last blocks of these two 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. end of the hot part.
Only blocks of the warm part can be used for replacement. Only blocks of the warm part can be used for replacement.
The first block from the beginning of this subchain is always 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 +------+ | | +------+ W A R M +------+ |
+----| beg |---->...----| end |----+ +----| beg |---->...----| end |----+
+------+ +------+ins +------+ +------+ins
first for eviction first for eviction
*/ */
static void link_block(KEY_CACHE *keycache, BLOCK_LINK *block, my_bool hot, static void link_block(KEY_CACHE *keycache, BLOCK_LINK *block, my_bool hot,
my_bool at_end) my_bool at_end)
{ {
BLOCK_LINK *ins; BLOCK_LINK *ins;
BLOCK_LINK **pins; BLOCK_LINK **pins;
@ -881,7 +888,7 @@ static void link_block(KEY_CACHE *keycache, BLOCK_LINK *block, my_bool hot,
return; return;
} }
pins= hot ? &keycache->used_ins : &keycache->used_last; pins= hot ? &keycache->used_ins : &keycache->used_last;
ins= *pins; ins= *pins;
if (ins) if (ins)
{ {
ins->next_used->prev_used= &block->next_used; 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 SYNOPSIS
unlink_block() 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 block pointer to the block to unlink from the LRU chain
RETURN VALUE 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); keycache->used_last= STRUCT_PTR(BLOCK_LINK, next_used, block->prev_used);
if (keycache->used_ins == block) if (keycache->used_ins == block)
keycache->used_ins=STRUCT_PTR(BLOCK_LINK, next_used, block->prev_used); keycache->used_ins=STRUCT_PTR(BLOCK_LINK, next_used, block->prev_used);
} }
block->next_used= NULL; block->next_used= NULL;
KEYCACHE_THREAD_TRACE("unlink_block"); KEYCACHE_THREAD_TRACE("unlink_block");
@ -972,27 +979,27 @@ static void reg_requests(KEY_CACHE *keycache, BLOCK_LINK *block, int count)
SYNOPSIS SYNOPSIS
unreg_block() 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 block pointer to the block to link to the LRU chain
at_end <-> to link the block at the end of the LRU chain at_end <-> to link the block at the end of the LRU chain
RETURN VALUE RETURN VALUE
none none
NOTES. NOTES.
Every linking to the LRU chain decrements by one a special block 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 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. 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 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 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 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 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 Thus a warm block can be promoted to the hot sub-chain when its counter
becomes zero for the first time. becomes zero for the first time.
At the same time the block at the very beginning of the hot subchain 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 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, 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 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) int file, my_off_t filepos)
{ {
reg1 HASH_LINK *hash_link, **start; 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; 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 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. return the lru block after saving its buffer if the page is dirty.
SYNOPSIS SYNOPSIS
find_key_block() 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 file handler for the file to read page from
filepos position of the page in the file filepos position of the page in the file
init_hits_left how initialize the block counter for the page init_hits_left how initialize the block counter for the page
wrmode <-> get for writing 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 RETURN VALUE
Pointer to the found block if successful, 0 - otherwise 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 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 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 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: The function returns in the page_st parameter the following values:
PAGE_READ - if page already in the block, PAGE_READ - if page already in the block,
PAGE_TO_BE_READ - if it is to be read yet by the current thread 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. 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) - 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 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, static BLOCK_LINK *find_key_block(KEY_CACHE *keycache,
@ -1388,9 +1395,11 @@ restart:
The call is thread safe because only the current The call is thread safe because only the current
thread might change the block->hash_link value thread might change the block->hash_link value
*/ */
error=my_pwrite(block->hash_link->file, block->buffer, error= my_pwrite(block->hash_link->file,
block->length, block->hash_link->diskpos, block->buffer+block->offset,
MYF(MY_NABP | MY_WAIT_IF_FULL)); block->length - block->offset,
block->hash_link->diskpos+ block->offset,
MYF(MY_NABP | MY_WAIT_IF_FULL));
keycache_pthread_mutex_lock(&keycache->cache_lock); keycache_pthread_mutex_lock(&keycache->cache_lock);
if (keycache->env) if (keycache->env)
keycache->env->cache_write++; keycache->env->cache_write++;
@ -1465,12 +1474,12 @@ restart:
SYNOPSIS SYNOPSIS
read_block() 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 block block to which buffer the data is to be read
read_length size of data to be read read_length size of data to be read
min_length at least so much data must be read min_length at least so much data must be read
primary <-> the current thread will read the data primary <-> the current thread will read the data
RETURN VALUE RETURN VALUE
None None
@ -1551,15 +1560,15 @@ static void read_block(KEY_CACHE *keycache,
SYNOPSIS SYNOPSIS
key_cache_read() 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 file handler for the file for the block of data to be read
filepos position of the block of data in the file filepos position of the block of data in the file
level determines the weight of the data 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 length length of the buffer
block_length length of the block in the key cache buffer block_length length of the block in the key cache buffer
return_buffer return pointer to the key cache buffer with the data return_buffer return pointer to the key cache buffer with the data
RETURN VALUE RETURN VALUE
Returns address from where the data is placed if sucessful, 0 - otherwise. 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", DBUG_PRINT("enter", ("file %u, filepos %lu, length %u",
(uint) file, (ulong) filepos, length)); (uint) file, (ulong) filepos, length));
if (keycache->disk_blocks > 0) if (keycache && keycache->disk_blocks > 0)
{ {
/* Key cache is used */ /* Key cache is used */
reg1 BLOCK_LINK *block; 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) if (block->status != BLOCK_ERROR && page_st != PAGE_READ)
{ {
/* The requested page is to be read into the block buffer */ /* 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, keycache->key_cache_block_size, read_length+offset,
(my_bool)(page_st == PAGE_TO_BE_READ)); (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 */ /* Key cache is not used */
if (keycache->env) if (keycache && keycache->env)
{ {
statistic_increment(keycache->env->cache_r_requests, statistic_increment(keycache->env->cache_r_requests,
&keycache->cache_lock); &keycache->cache_lock);
@ -1696,13 +1705,13 @@ byte *key_cache_read(KEY_CACHE_HANDLE keycache,
SYNOPSIS SYNOPSIS
key_cache_insert() 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 file handler for the file to insert data from
filepos position of the block of data in the file to insert filepos position of the block of data in the file to insert
level determines the weight of the data level determines the weight of the data
buff buffer to read data from buff buffer to read data from
length length of the data in the buffer length length of the data in the buffer
RETURN VALUE RETURN VALUE
0 if a success, 1 - otherwise. 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 SYNOPSIS
key_cache_write() 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 file handler for the file to write data to
filepos position in the file to write data to filepos position in the file to write data to
level determines the weight of the data level determines the weight of the data
buff buffer with the data buff buffer with the data
length length of the buffer length length of the buffer
dont_write if is 0 then all dirty pages involved in writing 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 RETURN VALUE
0 if a success, 1 - otherwise. 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 The function copies the data of size length from buff into buffers
for key cache blocks that are assigned to contain the portion of for key cache blocks that are assigned to contain the portion of
the file starting with position filepos. 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 Filepos must be a multiple of 'block_length', but it doesn't
have to be a multiple of key_cache_block_size; 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; reg1 BLOCK_LINK *block;
int error=0; int error=0;
DBUG_ENTER("key_cache_write"); DBUG_ENTER("key_cache_write");
DBUG_PRINT("enter", ("file %u, filepos %lu, length %u block_length %u", DBUG_PRINT("enter",
(uint) file, (ulong) filepos, length, block_length)); ("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) if (!dont_write)
{ {
/* Force writing from buff into disk */ /* Force writing from buff into disk */
if (keycache->env) if (keycache && keycache->env)
statistic_increment(keycache->env->cache_write, statistic_increment(keycache->env->cache_write,
&keycache->cache_lock); &keycache->cache_lock);
if (my_pwrite(file, buff, length, filepos, MYF(MY_NABP | MY_WAIT_IF_FULL))) 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);); test_key_cache(keycache, "start of key_cache_write", 1););
#endif #endif
if (keycache->disk_blocks > 0) if (keycache && keycache->disk_blocks > 0)
{ {
/* Key cache is used */ /* Key cache is used */
uint read_length; uint read_length;
@ -1872,7 +1882,7 @@ int key_cache_write(KEY_CACHE_HANDLE keycache,
if (! (block->status & BLOCK_ERROR)) if (! (block->status & BLOCK_ERROR))
{ {
if (!(read_length & 511)) if (!(read_length & 511))
bmove512(block->buffer+offset, buff, read_length); bmove512(block->buffer+offset, buff, read_length);
else else
memcpy(block->buffer+offset, buff, (size_t) read_length); 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 */ /* Key cache is not used */
if (dont_write) if (dont_write)
{ {
if (keycache->env) if (keycache && keycache->env)
{ {
statistic_increment(keycache->env->cache_w_requests, statistic_increment(keycache->env->cache_w_requests,
&keycache->cache_lock); &keycache->cache_lock);
statistic_increment(keycache->env->cache_write, statistic_increment(keycache->env->cache_write,
&keycache->cache_lock); &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))) MYF(MY_NABP | MY_WAIT_IF_FULL)))
error=1; error=1;
} }
@ -1991,8 +2001,10 @@ static int flush_cached_blocks(KEY_CACHE *keycache,
KEYCACHE_DBUG_PRINT("flush_cached_blocks", KEYCACHE_DBUG_PRINT("flush_cached_blocks",
("block %u to be flushed", BLOCK_NUMBER(block))); ("block %u to be flushed", BLOCK_NUMBER(block)));
keycache_pthread_mutex_unlock(&keycache->cache_lock); keycache_pthread_mutex_unlock(&keycache->cache_lock);
error= my_pwrite(file, block->buffer+block->offset, block->length, error= my_pwrite(file,
block->hash_link->diskpos, block->buffer+block->offset,
block->length - block->offset,
block->hash_link->diskpos+ block->offset,
MYF(MY_NABP | MY_WAIT_IF_FULL)); MYF(MY_NABP | MY_WAIT_IF_FULL));
keycache_pthread_mutex_lock(&keycache->cache_lock); keycache_pthread_mutex_lock(&keycache->cache_lock);
if (keycache->env) if (keycache->env)
@ -2024,27 +2036,30 @@ static int flush_cached_blocks(KEY_CACHE *keycache,
/* /*
Flush all blocks for a file to disk flush all key blocks for a file to disk, but don't do any mutex locks
SYNOPSIS
flush_key_blocks() 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 file handler for the file to flush to
flush_type type of the flush flush_type type of the flush
RETURN VALUE
0 if a success, 1 - otherwise.
*/
int flush_key_blocks(KEY_CACHE_HANDLE keycache, NOTES
File file, enum flush_type type) 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; KEY_CACHE_VAR *env;
BLOCK_LINK *cache_buff[FLUSH_CACHE],**cache; BLOCK_LINK *cache_buff[FLUSH_CACHE],**cache;
int last_errno= 0; int last_errno= 0;
DBUG_ENTER("flush_key_blocks_int");
DBUG_ENTER("flush_key_blocks");
DBUG_PRINT("enter",("file: %d blocks_used: %d blocks_changed: %d", DBUG_PRINT("enter",("file: %d blocks_used: %d blocks_changed: %d",
file, keycache->blocks_used, keycache->blocks_changed)); 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);); test_key_cache(keycache, "start of flush_key_blocks", 0););
#endif #endif
keycache_pthread_mutex_lock(&keycache->cache_lock);
cache= cache_buff; cache= cache_buff;
if (keycache->disk_blocks > 0 && if (keycache->disk_blocks > 0 &&
(!my_disable_flush_key_blocks || type != FLUSH_KEEP)) (!my_disable_flush_key_blocks || type != FLUSH_KEEP))
@ -2132,7 +2145,7 @@ restart:
This happens only if there is not enough This happens only if there is not enough
memory for the big block memory for the big block
*/ */
if ((error= flush_cached_blocks(keycache, file, cache, if ((error= flush_cached_blocks(keycache, file, cache,
end,type))) end,type)))
last_errno=error; last_errno=error;
/* /*
@ -2214,12 +2227,8 @@ restart:
} }
} }
keycache_pthread_mutex_unlock(&keycache->cache_lock);
if (type == FLUSH_REMOVE && (env= keycache->env) && (env->action)) if (type == FLUSH_REMOVE && (env= keycache->env) && (env->action))
{
(*env->action)((void *) env); (*env->action)((void *) env);
}
#ifndef DBUG_OFF #ifndef DBUG_OFF
DBUG_EXECUTE("check_keycache", DBUG_EXECUTE("check_keycache",
@ -2233,6 +2242,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 Flush all blocks in the key cache to disk
*/ */
@ -2253,7 +2293,8 @@ static int flush_all_key_blocks(KEY_CACHE *keycache)
cnt++; cnt++;
KEYCACHE_DBUG_ASSERT(cnt <= keycache->blocks_used); KEYCACHE_DBUG_ASSERT(cnt <= keycache->blocks_used);
#endif #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; return 1;
break; break;
} }

359
mysys/mf_keycaches.c Normal file
View File

@ -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);
}

View File

@ -38,6 +38,7 @@
#include <assert.h> #include <assert.h>
#include <m_string.h> #include <m_string.h>
inline void bitmap_lock(MY_BITMAP *map) inline void bitmap_lock(MY_BITMAP *map)
{ {
#ifdef THREAD #ifdef THREAD
@ -46,6 +47,7 @@ inline void bitmap_lock(MY_BITMAP *map)
#endif #endif
} }
inline void bitmap_unlock(MY_BITMAP *map) inline void bitmap_unlock(MY_BITMAP *map)
{ {
#ifdef THREAD #ifdef THREAD
@ -54,14 +56,19 @@ inline void bitmap_unlock(MY_BITMAP *map)
#endif #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); DBUG_ASSERT((bitmap_size & 7) == 0);
bitmap_size/=8; bitmap_size/=8;
if (!(map->bitmap=buf) && if (!(map->bitmap=buf) &&
!(map->bitmap=(uchar*)my_malloc(bitmap_size + !(map->bitmap= (uchar*) my_malloc(bitmap_size +
(thread_safe ? sizeof(pthread_mutex_t) : 0), (thread_safe ?
MYF(MY_WME | MY_ZEROFILL)))) sizeof(pthread_mutex_t) : 0),
MYF(MY_WME | MY_ZEROFILL))))
return 1; return 1;
map->bitmap_size=bitmap_size; map->bitmap_size=bitmap_size;
#ifdef THREAD #ifdef THREAD
@ -73,22 +80,26 @@ my_bool bitmap_init(MY_BITMAP *map, uchar *buf, uint bitmap_size, my_bool thread
else else
map->mutex=0; map->mutex=0;
#endif #endif
return 0; DBUG_RETURN(0);
} }
void bitmap_free(MY_BITMAP *map) void bitmap_free(MY_BITMAP *map)
{ {
#ifdef THREAD DBUG_ENTER("bitmap_free");
if (map->mutex)
pthread_mutex_destroy(map->mutex);
#endif
if (map->bitmap) if (map->bitmap)
{ {
#ifdef THREAD
if (map->mutex)
pthread_mutex_destroy(map->mutex);
#endif
my_free((char*) map->bitmap, MYF(0)); my_free((char*) map->bitmap, MYF(0));
map->bitmap=0; map->bitmap=0;
} }
DBUG_VOID_RETURN;
} }
void bitmap_set_bit(MY_BITMAP *map, uint bitmap_bit) void bitmap_set_bit(MY_BITMAP *map, uint bitmap_bit)
{ {
DBUG_ASSERT(map->bitmap && bitmap_bit < map->bitmap_size*8); 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); bitmap_unlock(map);
} }
uint bitmap_set_next(MY_BITMAP *map) uint bitmap_set_next(MY_BITMAP *map)
{ {
uchar *bitmap=map->bitmap; uchar *bitmap=map->bitmap;
@ -127,6 +139,7 @@ uint bitmap_set_next(MY_BITMAP *map)
return bit_found; return bit_found;
} }
void bitmap_clear_bit(MY_BITMAP *map, uint bitmap_bit) void bitmap_clear_bit(MY_BITMAP *map, uint bitmap_bit)
{ {
DBUG_ASSERT(map->bitmap && bitmap_bit < map->bitmap_size*8); 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); bitmap_unlock(map);
} }
void bitmap_set_prefix(MY_BITMAP *map, uint prefix_size) void bitmap_set_prefix(MY_BITMAP *map, uint prefix_size)
{ {
uint prefix_bytes, prefix_bits; uint prefix_bytes, prefix_bits;
DBUG_ASSERT(map->bitmap && 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); bitmap_lock(map);
set_if_smaller(prefix_size, map->bitmap_size*8); set_if_smaller(prefix_size, map->bitmap_size*8);
if ((prefix_bytes= prefix_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); bitmap_unlock(map);
} }
void bitmap_clear_all(MY_BITMAP *map) void bitmap_clear_all(MY_BITMAP *map)
{ {
bitmap_set_prefix(map, 0); bitmap_set_prefix(map, 0);
} }
void bitmap_set_all(MY_BITMAP *map) void bitmap_set_all(MY_BITMAP *map)
{ {
bitmap_set_prefix(map, ~0); bitmap_set_prefix(map, ~0);
} }
my_bool bitmap_is_prefix(const MY_BITMAP *map, uint prefix_size) my_bool bitmap_is_prefix(const MY_BITMAP *map, uint prefix_size)
{ {
uint prefix_bits= prefix_size & 7, res= 0; uint prefix_bits= prefix_size & 7, res= 0;
@ -188,6 +205,7 @@ ret:
return res; return res;
} }
my_bool bitmap_is_clear_all(const MY_BITMAP *map) my_bool bitmap_is_clear_all(const MY_BITMAP *map)
{ {
return bitmap_is_prefix(map, 0); 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); return bitmap_is_prefix(map, map->bitmap_size*8);
} }
my_bool bitmap_is_set(const MY_BITMAP *map, uint bitmap_bit) my_bool bitmap_is_set(const MY_BITMAP *map, uint bitmap_bit)
{ {
DBUG_ASSERT(map->bitmap && bitmap_bit < map->bitmap_size*8); DBUG_ASSERT(map->bitmap && bitmap_bit < map->bitmap_size*8);
return map->bitmap[bitmap_bit / 8] & (1 << (bitmap_bit & 7)); return map->bitmap[bitmap_bit / 8] & (1 << (bitmap_bit & 7));
} }
my_bool bitmap_is_subset(const MY_BITMAP *map1, const MY_BITMAP *map2) 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; uchar *m1=map1->bitmap, *m2=map2->bitmap, *end;
DBUG_ASSERT(map1->bitmap && map2->bitmap && 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; end= m1+map1->bitmap_size;
while (m1 < end) while (m1 < end)
{
if ((*m1++) & ~(*m2++)) if ((*m1++) & ~(*m2++))
goto ret; goto ret;
}
res=1; res=1;
ret: ret:
@ -227,6 +249,7 @@ ret:
return res; return res;
} }
my_bool bitmap_cmp(const MY_BITMAP *map1, const MY_BITMAP *map2) my_bool bitmap_cmp(const MY_BITMAP *map1, const MY_BITMAP *map2)
{ {
uint res; uint res;
@ -243,6 +266,7 @@ my_bool bitmap_cmp(const MY_BITMAP *map1, const MY_BITMAP *map2)
return res; return res;
} }
void bitmap_intersect(MY_BITMAP *map, const MY_BITMAP *map2) void bitmap_intersect(MY_BITMAP *map, const MY_BITMAP *map2)
{ {
uchar *to=map->bitmap, *from=map2->bitmap, *end; 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); bitmap_unlock(map);
} }
void bitmap_subtract(MY_BITMAP *map, const MY_BITMAP *map2) void bitmap_subtract(MY_BITMAP *map, const MY_BITMAP *map2)
{ {
uchar *to=map->bitmap, *from=map2->bitmap, *end; 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); bitmap_unlock(map);
} }
void bitmap_union(MY_BITMAP *map, const MY_BITMAP *map2) void bitmap_union(MY_BITMAP *map, const MY_BITMAP *map2)
{ {
uchar *to=map->bitmap, *from=map2->bitmap, *end; uchar *to=map->bitmap, *from=map2->bitmap, *end;

View File

@ -682,60 +682,77 @@ ulonglong getopt_ull_limit_value(ulonglong num, const struct my_option *optp)
return num; 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 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) static void init_variables(const struct my_option *options)
{ {
for (; options->name; options++) for (; options->name; options++)
{ {
gptr *value= (options->var_type & GET_ASK_ADDR ? gptr *variable;
(*getopt_get_addr)("", 0, options) : options->value); /*
if (value) We must set u_max_value first as for some variables
{ options->u_max_value == options->value and in this case we want to
switch ((options->var_type & GET_TYPE_MASK)) { set the value to default value.
case GET_BOOL: */
if (options->u_max_value) if (options->u_max_value)
*((my_bool*) options->u_max_value)= (my_bool) options->max_value; init_one_value(options, options->u_max_value, options->max_value);
*((my_bool*) value)= (my_bool) options->def_value; if (options->value)
break; init_one_value(options, options->value, options->def_value);
case GET_INT: if (options->var_type & GET_ASK_ADDR &&
if (options->u_max_value) (variable= (*getopt_get_addr)("", 0, options)))
*((int*) options->u_max_value)= (int) options->max_value; init_one_value(options, variable, options->def_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;
}
}
} }
} }

View File

@ -28,7 +28,7 @@ pthread_key(struct st_my_thread_var*, THR_KEY_mysys);
#else #else
pthread_key(struct st_my_thread_var, THR_KEY_mysys); pthread_key(struct st_my_thread_var, THR_KEY_mysys);
#endif /* USE_TLS */ #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_lock,THR_LOCK_isam,THR_LOCK_myisam,THR_LOCK_heap,
THR_LOCK_net, THR_LOCK_charset; THR_LOCK_net, THR_LOCK_charset;
#if !defined(HAVE_LOCALTIME_R) || !defined(HAVE_GMTIME_R) #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_malloc,MY_MUTEX_INIT_FAST);
pthread_mutex_init(&THR_LOCK_open,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_lock,MY_MUTEX_INIT_FAST);
pthread_mutex_init(&THR_LOCK_isam,MY_MUTEX_INIT_SLOW); pthread_mutex_init(&THR_LOCK_isam,MY_MUTEX_INIT_SLOW);
pthread_mutex_init(&THR_LOCK_myisam,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 #endif
pthread_mutex_destroy(&THR_LOCK_malloc); pthread_mutex_destroy(&THR_LOCK_malloc);
pthread_mutex_destroy(&THR_LOCK_open); pthread_mutex_destroy(&THR_LOCK_open);
pthread_mutex_destroy(&THR_LOCK_keycache);
pthread_mutex_destroy(&THR_LOCK_lock); pthread_mutex_destroy(&THR_LOCK_lock);
pthread_mutex_destroy(&THR_LOCK_isam); pthread_mutex_destroy(&THR_LOCK_isam);
pthread_mutex_destroy(&THR_LOCK_myisam); pthread_mutex_destroy(&THR_LOCK_myisam);

View File

@ -20,15 +20,28 @@
#include <m_string.h> #include <m_string.h>
#include <m_ctype.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 Search after a string in a list of strings. Endspace in x is not compared.
** to full field.
** full_name has the following bit values: SYNOPSIS
** If & 1 accept only whole names find_type()
** If & 2 don't expand if half field x String to find
** If & 4 allow #number# as type 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) int find_type(my_string x, TYPELIB *typelib, uint full_name)
{ {

View File

@ -754,7 +754,15 @@ mysql_free_result(MYSQL_RES *result)
if ((pkt_len=net_safe_read(result->handle)) == packet_error) if ((pkt_len=net_safe_read(result->handle)) == packet_error)
break; break;
if (pkt_len <= 8 && result->handle->net.read_pos[0] == 254) 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 */ break; /* End of data */
}
} }
result->handle->status=MYSQL_STATUS_READY; 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; options->client_flag|= CLIENT_MULTI_RESULTS;
break; break;
case 31: case 31:
options->client_flag|= CLIENT_MULTI_QUERIES | CLIENT_MULTI_RESULTS; options->client_flag|= CLIENT_MULTI_STATEMENTS | CLIENT_MULTI_RESULTS;
break; break;
default: default:
DBUG_PRINT("warning",("unknown option: %s",option[0])); 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 */ if (pkt_len > 1) /* MySQL 4.1 protocol */
{ {
mysql->warning_count= uint2korr(cp+1); mysql->warning_count= uint2korr(cp+1);
mysql->server_status= uint2korr(cp+3);
DBUG_PRINT("info",("warning_count: %ld", mysql->warning_count)); DBUG_PRINT("info",("warning_count: %ld", mysql->warning_count));
} }
DBUG_PRINT("exit",("Got %d rows",result->rows)); 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 <= 8 && net->read_pos[0] == 254)
{ {
if (pkt_len > 1) /* MySQL 4.1 protocol */ if (pkt_len > 1) /* MySQL 4.1 protocol */
{
mysql->warning_count= uint2korr(net->read_pos+1); mysql->warning_count= uint2korr(net->read_pos+1);
mysql->server_status= uint2korr(net->read_pos+3);
}
return 1; /* End of data */ return 1; /* End of data */
} }
prev_pos= 0; /* allowed to write at packet[-1] */ 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|=mysql->options.client_flag;
client_flag|=CLIENT_CAPABILITIES; client_flag|=CLIENT_CAPABILITIES;
if (client_flag & CLIENT_MULTI_QUERIES) if (client_flag & CLIENT_MULTI_STATEMENTS)
client_flag|= CLIENT_MULTI_RESULTS; client_flag|= CLIENT_MULTI_RESULTS;
#ifdef HAVE_OPENSSL #ifdef HAVE_OPENSSL

View File

@ -226,15 +226,10 @@ err:
int ha_myisam::open(const char *name, int mode, uint test_if_locked) 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))) if (!(file=mi_open(name, mode, test_if_locked)))
return (my_errno ? my_errno : -1); 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)) if (test_if_locked & (HA_OPEN_IGNORE_IF_LOCKED | HA_OPEN_TMP_TABLE))
VOID(mi_extra(file, HA_EXTRA_NO_WAIT_LOCK, 0)); VOID(mi_extra(file, HA_EXTRA_NO_WAIT_LOCK, 0));
info(HA_STATUS_NO_LOCK | HA_STATUS_VARIABLE | HA_STATUS_CONST); 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) int ha_myisam::assign_to_keycache(THD* thd, HA_CHECK_OPT *check_opt)
{ {
uint len; KEY_CACHE_VAR *new_key_cache= check_opt->key_cache;
KEY_CACHE_VAR *old_key_cache; const char *errmsg= 0;
KEY_CACHE_VAR *new_key_cache;
const char *errmsg=0;
int error= HA_ADMIN_OK; int error= HA_ADMIN_OK;
ulonglong map= ~(ulonglong) 0; ulonglong map= ~(ulonglong) 0;
TABLE_LIST *table_list= table->pos_in_table_list; 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"); 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 */ /* 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; key_map kmap;
get_key_map_from_key_list(&kmap, table, table_list->use_index); if (get_key_map_from_key_list(&kmap, table, table_list->use_index))
if (kmap.is_set_all())
{ {
errmsg= thd->net.last_error; errmsg= thd->net.last_error;
error= HA_ADMIN_FAILED; error= HA_ADMIN_FAILED;
goto err; goto err;
} }
if (!kmap.is_clear_all()) map= kmap.to_ulonglong();
map= kmap.to_ulonglong();
} }
len= strlen(new_key_cache_name); if ((error= mi_assign_to_key_cache(file, map, new_key_cache)))
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;
}
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)
{ {
switch (error) { switch (error) {
default: default:
char buf[ERRMSGSIZE+20]; char buf[80];
my_snprintf(buf, ERRMSGSIZE, my_snprintf(buf, sizeof(buf),
"Failed to flush to index file (errno: %d)", my_errno); "Failed to flush to index file (errno: %d)", error);
errmsg= buf; errmsg= buf;
} }
error= HA_ADMIN_CORRUPT; error= HA_ADMIN_CORRUPT;
goto err;
} }
goto ok;
err: err:
if (!triggered) if (error != HA_ADMIN_OK)
{ {
/* Send error to user */
MI_CHECK param; MI_CHECK param;
myisamchk_init(&param); myisamchk_init(&param);
param.thd= thd; 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.table_name= table->table_name;
param.testflag= 0; param.testflag= 0;
mi_check_print_error(&param, errmsg); 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); DBUG_RETURN(error);
} }

View File

@ -35,9 +35,12 @@
const char **ha_myisammrg::bas_ext() const const char **ha_myisammrg::bas_ext() const
{ static const char *ext[]= { ".MRG", NullS }; return ext; } { static const char *ext[]= { ".MRG", NullS }; return ext; }
int ha_myisammrg::open(const char *name, int mode, uint test_if_locked) int ha_myisammrg::open(const char *name, int mode, uint test_if_locked)
{ {
char name_buff[FN_REFLEN]; char name_buff[FN_REFLEN];
KEY_CACHE_VAR *key_cache;
DBUG_PRINT("info", ("ha_myisammrg::open")); DBUG_PRINT("info", ("ha_myisammrg::open"));
if (!(file=myrg_open(fn_format(name_buff,name,"","",2 | 4), mode, if (!(file=myrg_open(fn_format(name_buff,name,"","",2 | 4), mode,
test_if_locked))) 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)); DBUG_PRINT("info", ("ha_myisammrg::open exit %d", my_errno));
return (my_errno ? my_errno : -1); 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...")) DBUG_PRINT("info", ("ha_myisammrg::open myrg_extrafunc..."))
myrg_extrafunc(file, query_cache_invalidate_by_MyISAM_filename_ref); myrg_extrafunc(file, query_cache_invalidate_by_MyISAM_filename_ref);
if (!(test_if_locked == HA_OPEN_WAIT_IF_LOCKED || if (!(test_if_locked == HA_OPEN_WAIT_IF_LOCKED ||

View File

@ -1105,67 +1105,6 @@ int ha_create_table(const char *name, HA_CREATE_INFO *create_info,
DBUG_RETURN(error != 0); DBUG_RETURN(error != 0);
} }
/* Use key cacheing on all databases */
int ha_key_cache(KEY_CACHE_VAR *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);
}
return 0;
}
int ha_resize_key_cache(KEY_CACHE_VAR *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);
}
return 0;
}
int ha_change_key_cache_param(KEY_CACHE_VAR *key_cache)
{
if (key_cache->cache)
{
change_key_cache_param(key_cache->cache);
}
return 0;
}
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;
}
return 0;
}
static int NEAR_F delete_file(const char *name,const char *ext,int extflag) static int NEAR_F delete_file(const char *name,const char *ext,int extflag)
{ {
char buff[FN_REFLEN]; char buff[FN_REFLEN];
@ -1178,3 +1117,85 @@ void st_ha_check_opt::init()
flags= sql_flags= 0; flags= sql_flags= 0;
sort_buffer_size = current_thd->variables.myisam_sort_buff_size; 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_init_key_cache(const char *name, KEY_CACHE_VAR *key_cache)
{
DBUG_ENTER("ha_init_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);
DBUG_RETURN(!init_key_cache(&key_cache->cache,
tmp_block_size,
tmp_buff_size,
key_cache));
}
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);
DBUG_RETURN(!resize_key_cache(&key_cache->cache, tmp_block_size,
tmp_buff_size));
}
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); // Can never fail
key_cache->cache= 0;
}
return 0;
}
/* Move all tables from one key cache to another one */
int ha_change_key_cache(KEY_CACHE_VAR *old_key_cache,
KEY_CACHE_VAR *new_key_cache)
{
mi_change_key_cache(old_key_cache, new_key_cache);
return 0;
}

View File

@ -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_AVG_ROW_LENGTH 64
#define HA_CREATE_USED_PACK_KEYS 128 #define HA_CREATE_USED_PACK_KEYS 128
#define HA_CREATE_USED_CHARSET 256 #define HA_CREATE_USED_CHARSET 256
#define HA_CREATE_USED_DEFAULT_CHARSET 512
typedef struct st_thd_trans { typedef struct st_thd_trans {
void *bdb_tid; void *bdb_tid;
@ -157,7 +158,7 @@ enum enum_tx_isolation { ISO_READ_UNCOMMITTED, ISO_READ_COMMITTED,
typedef struct st_ha_create_information typedef struct st_ha_create_information
{ {
CHARSET_INFO *table_charset; CHARSET_INFO *table_charset, *default_table_charset;
char *comment,*password; char *comment,*password;
char *data_file_name, *index_file_name; char *data_file_name, *index_file_name;
ulonglong max_rows,min_rows; ulonglong max_rows,min_rows;
@ -180,15 +181,18 @@ typedef struct st_ha_create_information
struct st_table; struct st_table;
typedef struct st_table TABLE; typedef struct st_table TABLE;
typedef struct st_key_cache_asmt KEY_CACHE_ASMT;
typedef struct st_ha_check_opt typedef struct st_ha_check_opt
{ {
ulong sort_buffer_size; ulong sort_buffer_size;
uint flags; /* isam layer flags (e.g. for myisamchk) */ uint flags; /* isam layer flags (e.g. for myisamchk) */
uint sql_flags; /* sql layer flags - for something myisamchk cannot do */ 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(); void init();
} HA_CHECK_OPT; } HA_CHECK_OPT;
class handler :public Sql_alloc class handler :public Sql_alloc
{ {
protected: protected:
@ -390,7 +394,7 @@ int ha_create_table(const char *name, HA_CREATE_INFO *create_info,
bool update_create_info); bool update_create_info);
int ha_delete_table(enum db_type db_type, const char *path); int ha_delete_table(enum db_type db_type, const char *path);
void ha_drop_database(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_resize_key_cache(KEY_CACHE_VAR *key_cache);
int ha_change_key_cache_param(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); 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); void ha_set_spin_retries(uint retries);
bool ha_flush_logs(void); bool ha_flush_logs(void);
int ha_recovery_logging(THD *thd, bool on); 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);

View File

@ -125,9 +125,10 @@ public:
optimisation changes in prepared statements optimisation changes in prepared statements
*/ */
Item(THD *thd, Item &item); 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 set_name(const char *str,uint length, CHARSET_INFO *cs);
void init_make_field(Send_field *tmp_field,enum enum_field_types type); void init_make_field(Send_field *tmp_field,enum enum_field_types type);
virtual void cleanup() {}
virtual void make_field(Send_field *field); virtual void make_field(Send_field *field);
virtual bool fix_fields(THD *, struct st_table_list *, Item **); virtual bool fix_fields(THD *, struct st_table_list *, Item **);
virtual int save_in_field(Field *field, bool no_conversions); virtual int save_in_field(Field *field, bool no_conversions);

View File

@ -715,7 +715,14 @@ class Item_func_in :public Item_int_func
} }
longlong val_int(); longlong val_int();
void fix_length_and_dec(); 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 optimize_type select_optimize() const
{ return array ? OPTIMIZE_KEY : OPTIMIZE_NONE; } { return array ? OPTIMIZE_KEY : OPTIMIZE_NONE; }
void print(String *str); void print(String *str);

View File

@ -2652,6 +2652,8 @@ err:
void Item_func_match::init_search(bool no_order) void Item_func_match::init_search(bool no_order)
{ {
DBUG_ENTER("Item_func_match::init_search"); DBUG_ENTER("Item_func_match::init_search");
/* Check if init_search() has been called before */
if (ft_handler) if (ft_handler)
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
@ -2689,7 +2691,8 @@ void Item_func_match::init_search(bool no_order)
ft_tmp= &search_value; 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, ft_handler=table->file->ft_init_ext(flags, key,
(byte*) ft_tmp->ptr(), (byte*) ft_tmp->ptr(),
ft_tmp->length()); ft_tmp->length());

View File

@ -427,8 +427,6 @@ bool check_stack_overrun(THD *thd,char *dummy);
void table_cache_init(void); void table_cache_init(void);
void table_cache_free(void); void table_cache_free(void);
uint cached_tables(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, void reassign_key_cache(KEY_CACHE_ASMT *key_cache_asmt,
KEY_CACHE_VAR *new_key_cache); KEY_CACHE_VAR *new_key_cache);
void kill_mysql(void); void kill_mysql(void);
@ -460,10 +458,11 @@ int mysql_analyze_table(THD* thd, TABLE_LIST* table_list,
HA_CHECK_OPT* check_opt); HA_CHECK_OPT* check_opt);
int mysql_optimize_table(THD* thd, TABLE_LIST* table_list, int mysql_optimize_table(THD* thd, TABLE_LIST* table_list,
HA_CHECK_OPT* check_opt); 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 mysql_preload_keys(THD* thd, TABLE_LIST* table_list);
int reassign_keycache_tables(THD* thd, KEY_CACHE_VAR* src_cache, int reassign_keycache_tables(THD* thd, KEY_CACHE_VAR *src_cache,
char *dest_name, bool remove_fl); KEY_CACHE_VAR *dst_cache);
bool check_simple_select(); 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; extern const Item **not_found_item;
Item ** find_item_in_list(Item *item, List<Item> &items, uint *counter, Item ** find_item_in_list(Item *item, List<Item> &items, uint *counter,
find_item_error_report_type report_error); 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); List<String> *index_list);
bool insert_fields(THD *thd,TABLE_LIST *tables, bool insert_fields(THD *thd,TABLE_LIST *tables,
const char *db_name, const char *table_name, 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_error_log, LOCK_delayed_insert,
LOCK_delayed_status, LOCK_delayed_create, LOCK_crypt, LOCK_timezone, LOCK_delayed_status, LOCK_delayed_create, LOCK_crypt, LOCK_timezone,
LOCK_slave_list, LOCK_active_mi, LOCK_manager, 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 rw_lock_t LOCK_grant;
extern pthread_cond_t COND_refresh, COND_thread_count, COND_manager; extern pthread_cond_t COND_refresh, COND_thread_count, COND_manager;
extern pthread_attr_t connection_attrib; 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 global_system_variables;
extern struct system_variables max_system_variables; extern struct system_variables max_system_variables;
extern struct rand_struct sql_rand; 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 const char *opt_date_time_formats[];
extern KNOWN_DATE_TIME_FORMAT known_date_time_formats[]; extern KNOWN_DATE_TIME_FORMAT known_date_time_formats[];

View File

@ -355,6 +355,7 @@ struct system_variables max_system_variables;
MY_TMPDIR mysql_tmpdir_list; MY_TMPDIR mysql_tmpdir_list;
MY_BITMAP temp_pool; MY_BITMAP temp_pool;
KEY_CACHE_VAR *sql_key_cache;
CHARSET_INFO *system_charset_info, *files_charset_info ; CHARSET_INFO *system_charset_info, *files_charset_info ;
CHARSET_INFO *national_charset_info, *table_alias_charset; 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_delayed_insert, LOCK_delayed_status, LOCK_delayed_create,
LOCK_crypt, LOCK_bytes_sent, LOCK_bytes_received, LOCK_crypt, LOCK_bytes_sent, LOCK_bytes_received,
LOCK_global_system_variables, LOCK_global_system_variables,
LOCK_assign,
LOCK_user_conn, LOCK_slave_list, LOCK_active_mi; LOCK_user_conn, LOCK_slave_list, LOCK_active_mi;
rw_lock_t LOCK_grant; rw_lock_t LOCK_grant;
pthread_cond_t COND_refresh,COND_thread_count, COND_slave_stopped, pthread_cond_t COND_refresh,COND_thread_count, COND_slave_stopped,
@ -900,7 +900,6 @@ void clean_up(bool print_message)
#endif #endif
query_cache_destroy(); query_cache_destroy();
table_cache_free(); table_cache_free();
assign_cache_free();
hostname_cache_free(); hostname_cache_free();
item_user_lock_free(); item_user_lock_free();
lex_free(); /* Free some memory */ lex_free(); /* Free some memory */
@ -910,9 +909,8 @@ void clean_up(bool print_message)
udf_free(); udf_free();
#endif #endif
(void) ha_panic(HA_PANIC_CLOSE); /* close all tables and logs */ (void) ha_panic(HA_PANIC_CLOSE); /* close all tables and logs */
process_key_caches(&ha_end_key_cache); delete_elements(&key_caches, (void (*)(const char*, gptr)) free_key_cache);
ha_end_key_cache(&dflt_key_cache_var); multi_keycache_free();
delete_elements(&key_caches, free_key_cache);
end_thr_alarm(1); /* Free allocated memory */ end_thr_alarm(1); /* Free allocated memory */
#ifdef USE_RAID #ifdef USE_RAID
end_raid(); end_raid();
@ -997,7 +995,6 @@ static void clean_up_mutexes()
#endif #endif
(void) pthread_mutex_destroy(&LOCK_active_mi); (void) pthread_mutex_destroy(&LOCK_active_mi);
(void) pthread_mutex_destroy(&LOCK_global_system_variables); (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_thread_count);
(void) pthread_cond_destroy(&COND_refresh); (void) pthread_cond_destroy(&COND_refresh);
(void) pthread_cond_destroy(&COND_thread_cache); (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\ the problem, but since we have already crashed, something is definitely wrong\n\
and this may fail.\n\n"); and this may fail.\n\n");
fprintf(stderr, "key_buffer_size=%lu\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, "read_buffer_size=%ld\n", global_system_variables.read_buff_size);
fprintf(stderr, "max_used_connections=%ld\n", max_used_connections); fprintf(stderr, "max_used_connections=%ld\n", max_used_connections);
fprintf(stderr, "max_connections=%ld\n", max_connections); fprintf(stderr, "max_connections=%ld\n", max_connections);
fprintf(stderr, "threads_connected=%d\n", thread_count); fprintf(stderr, "threads_connected=%d\n", thread_count);
fprintf(stderr, "It is possible that mysqld could use up to \n\ 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\ 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.read_buff_size +
global_system_variables.sortbuff_size) * global_system_variables.sortbuff_size) *
max_connections)/ 1024); 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_user_conn, MY_MUTEX_INIT_FAST);
(void) pthread_mutex_init(&LOCK_active_mi, 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_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) my_rwlock_init(&LOCK_grant, NULL);
(void) pthread_cond_init(&COND_thread_count,NULL); (void) pthread_cond_init(&COND_thread_count,NULL);
(void) pthread_cond_init(&COND_refresh,NULL); (void) pthread_cond_init(&COND_refresh,NULL);
@ -2256,7 +2252,6 @@ static int init_server_components()
{ {
DBUG_ENTER("init_server_components"); DBUG_ENTER("init_server_components");
table_cache_init(); table_cache_init();
assign_cache_init();
hostname_cache_init(); hostname_cache_init();
query_cache_result_size_limit(query_cache_limit); query_cache_result_size_limit(query_cache_limit);
query_cache_set_min_res_unit(query_cache_min_res_unit); query_cache_set_min_res_unit(query_cache_min_res_unit);
@ -2328,9 +2323,10 @@ Now disabling --log-slave-updates.");
if (opt_myisam_log) if (opt_myisam_log)
(void) mi_log(1); (void) mi_log(1);
ha_key_cache(&dflt_key_cache_var); /* call ha_init_key_cache() on all key caches to init them */
process_key_caches(&ha_key_cache); 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 defined(HAVE_MLOCKALL) && defined(MCL_CURRENT)
if (locked_in_memory && !geteuid()) if (locked_in_memory && !geteuid())
@ -4321,25 +4317,28 @@ replicating a LOAD DATA INFILE command.",
{"key_buffer_size", OPT_KEY_BUFFER_SIZE, {"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.", "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,
(gptr*) &dflt_key_cache_var.buff_size, 0, (gptr*) 0,
(enum get_opt_var_type) (GET_ULL | GET_ASK_ADDR), 0, (enum get_opt_var_type) (GET_ULL | GET_ASK_ADDR),
REQUIRED_ARG, KEY_CACHE_SIZE, MALLOC_OVERHEAD, (long) ~0, MALLOC_OVERHEAD, REQUIRED_ARG, KEY_CACHE_SIZE, MALLOC_OVERHEAD, (long) ~0, MALLOC_OVERHEAD,
IO_SIZE, 0}, IO_SIZE, 0},
{"key_cache_block_size", OPT_KEY_CACHE_BLOCK_SIZE, {"key_cache_block_size", OPT_KEY_CACHE_BLOCK_SIZE,
"The default size of key cache blocks", "The default size of key cache blocks",
(gptr*) &dflt_key_cache_var.block_size, (gptr*) &dflt_key_cache_var.block_size,
(gptr*) &dflt_key_cache_var.block_size, 0, GET_ULONG, (gptr*) 0,
REQUIRED_ARG, KEY_CACHE_BLOCK_SIZE , 512, 1024*16, MALLOC_OVERHEAD, 512, 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, {"key_cache_division_limit", OPT_KEY_CACHE_DIVISION_LIMIT,
"The minimum percentage of warm blocks in key cache", "The minimum percentage of warm blocks in key cache",
(gptr*) &dflt_key_cache_var.division_limit, (gptr*) &dflt_key_cache_var.division_limit,
(gptr*) &dflt_key_cache_var.division_limit, 0, GET_ULONG, (gptr*) 0,
REQUIRED_ARG, 100, 1, 100, 0, 1, 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, {"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", "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,
(gptr*) &dflt_key_cache_var.age_threshold, 0, GET_ULONG, (gptr*) 0,
REQUIRED_ARG, 300, 100, ~0L, 0, 100, 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, {"long_query_time", OPT_LONG_QUERY_TIME,
"Log all queries that have taken more than long_query_time seconds to execute to file.", "Log all queries that have taken more than long_query_time seconds to execute to file.",
(gptr*) &global_system_variables.long_query_time, (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_rollback", (char*) &ha_rollback_count, SHOW_LONG},
{"Handler_update", (char*) &ha_update_count, SHOW_LONG}, {"Handler_update", (char*) &ha_update_count, SHOW_LONG},
{"Handler_write", (char*) &ha_write_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, {"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, {"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, {"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, {"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, {"Key_writes", (char*) &dflt_key_cache_var.cache_write,
SHOW_LONG}, SHOW_KEY_CACHE_LONG},
{"Max_used_connections", (char*) &max_used_connections, SHOW_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}, {"Not_flushed_delayed_rows", (char*) &delayed_rows_in_use, SHOW_LONG_CONST},
{"Open_tables", (char*) 0, SHOW_OPENTABLES}, {"Open_tables", (char*) 0, SHOW_OPENTABLES},
{"Open_files", (char*) &my_file_opened, SHOW_LONG_CONST}, {"Open_files", (char*) &my_file_opened, SHOW_LONG_CONST},
@ -4984,8 +4983,9 @@ static void mysql_init_variables(void)
threads.empty(); threads.empty();
thread_cache.empty(); thread_cache.empty();
key_caches.empty(); key_caches.empty();
if (!get_or_create_key_cache(DEFAULT_KEY_CACHE_NAME, multi_keycache_init();
strlen(DEFAULT_KEY_CACHE_NAME))) if (!(sql_key_cache= get_or_create_key_cache(default_key_cache_base.str,
default_key_cache_base.length)))
exit(1); exit(1);
/* Initialize structures that is used when processing options */ /* Initialize structures that is used when processing options */
@ -5075,9 +5075,9 @@ static void mysql_init_variables(void)
have_crypt=SHOW_OPTION_NO; have_crypt=SHOW_OPTION_NO;
#endif #endif
#ifdef HAVE_COMPRESS #ifdef HAVE_COMPRESS
SHOW_COMP_OPTION have_compress= SHOW_OPTION_YES; have_compress= SHOW_OPTION_YES;
#else #else
SHOW_COMP_OPTION have_compress= SHOW_OPTION_NO; have_compress= SHOW_OPTION_NO;
#endif #endif
#ifdef HAVE_LIBWRAP #ifdef HAVE_LIBWRAP
libwrapName= NullS; libwrapName= NullS;
@ -5699,13 +5699,6 @@ static void get_options(int argc,char **argv)
init_global_datetime_format(TIMESTAMP_DATETIME, init_global_datetime_format(TIMESTAMP_DATETIME,
&global_system_variables.datetime_format)) &global_system_variables.datetime_format))
exit(1); 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;
} }

View File

@ -120,6 +120,10 @@ void send_error(THD *thd, uint sql_errno, const char *err)
#endif /* EMBEDDED_LIBRARY*/ #endif /* EMBEDDED_LIBRARY*/
thd->is_fatal_error=0; // Error message is given thd->is_fatal_error=0; // Error message is given
thd->net.report_error= 0; thd->net.report_error= 0;
/* Abort multi-result sets */
thd->lex.found_colon= 0;
thd->server_status= ~SERVER_MORE_RESULTS_EXISTS;
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
@ -338,7 +342,14 @@ send_eof(THD *thd, bool no_flush)
uint tmp= min(thd->total_warn_count, 65535); uint tmp= min(thd->total_warn_count, 65535);
buff[0]=254; buff[0]=254;
int2store(buff+1, tmp); 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(my_net_write(net,(char*) buff,5));
VOID(net_flush(net)); VOID(net_flush(net));
} }

View File

@ -60,11 +60,6 @@
#include "ha_innodb.h" #include "ha_innodb.h"
#endif #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; static HASH system_variable_hash;
const char *bool_type_names[]= { "OFF", "ON", NullS }; const char *bool_type_names[]= { "OFF", "ON", NullS };
TYPELIB bool_typelib= 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", sys_var_thd_ulong sys_join_buffer_size("join_buffer_size",
&SV::join_buff_size); &SV::join_buff_size);
sys_var_key_buffer_size sys_key_buffer_size("key_buffer_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_long sys_key_cache_block_size("key_cache_block_size",
sys_var_key_cache_division_limit offsetof(KEY_CACHE_VAR,
sys_key_cache_division_limit("key_cache_division_limit"); block_size));
sys_var_key_cache_age_threshold sys_var_key_cache_long sys_key_cache_division_limit("key_cache_division_limit",
sys_key_cache_age_threshold("key_cache_age_threshold"); 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", sys_var_bool_ptr sys_local_infile("local_infile",
&opt_local_infile); &opt_local_infile);
sys_var_thd_bool sys_log_warnings("log_warnings", &SV::log_warnings); 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()) { switch (type()) {
case SHOW_LONG: 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: case SHOW_LONGLONG:
{ {
longlong value; 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= 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 || safe_mutex_assert_owner(&LOCK_global_system_variables);
cache_name->str == default_key_cache_base.str || if (!cache_name || ! cache_name->length)
(cache_name->length == default_key_cache_base.length &&
!memcmp(cache_name->str, default_key_cache_base.str,
default_key_cache_base.length)))
cache_name= &default_key_cache_base; cache_name= &default_key_cache_base;
return ((KEY_CACHE_VAR*) find_named(&key_caches, return ((KEY_CACHE_VAR*) find_named(&key_caches,
cache_name->str, cache_name->length, cache_name->str, cache_name->length, 0));
0));
} }
byte *sys_var_key_cache_param::value_ptr(THD *thd, enum_var_type type, byte *sys_var_key_cache_param::value_ptr(THD *thd, enum_var_type type,
LEX_STRING *base) 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 ; return (byte*) key_cache + offset ;
} }
bool sys_var_key_buffer_size::update(THD *thd, set_var *var) bool sys_var_key_buffer_size::update(THD *thd, set_var *var)
{ {
ulonglong tmp= var->save_result.ulonglong_value; ulonglong tmp= var->save_result.ulonglong_value;
LEX_STRING *base_name= &var->base; 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) if (!base_name->length)
base_name= &default_key_cache_base; 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) if (!key_cache)
{ {
/* Key cache didn't exists */
if (!tmp) // Tried to delete cache if (!tmp) // Tried to delete cache
return 0; // Ok, nothing to do goto end; // Ok, nothing to do
if (!(key_cache= create_key_cache(base_name->str, if (!(key_cache= create_key_cache(base_name->str, base_name->length)))
base_name->length))) {
return 1; 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 (!tmp) // Zero size means delete
{ {
if (!key_cache->cache) if (key_cache == sql_key_cache)
return 0; goto end; // Ignore default key cache
/* Delete not default key caches */
if (key_cache != &dflt_key_cache_var) if (key_cache->cache) // If initied
{ {
/* /*
Move tables using this key cache to the default key cache Move tables using this key cache to the default key cache
and remove this key cache if no tables are assigned to it and clear the old key cache.
*/ */
NAMED_LIST *list; NAMED_LIST *list;
key_cache= (KEY_CACHE_VAR *) find_named(&key_caches, base_name->str, key_cache= (KEY_CACHE_VAR *) find_named(&key_caches, base_name->str,
base_name->length, &list); base_name->length, &list);
delete list; key_cache->in_init= 1;
int rc= reassign_keycache_tables(thd, key_cache, pthread_mutex_unlock(&LOCK_global_system_variables);
default_key_cache_base.str, 1); error= reassign_keycache_tables(thd, key_cache, sql_key_cache);
my_free((char*) key_cache, MYF(0)); pthread_mutex_lock(&LOCK_global_system_variables);
return rc; 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); 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) if (!key_cache->cache)
return (bool)(ha_key_cache(key_cache)); error= (bool) (ha_init_key_cache("", key_cache));
else else
return (bool)(ha_resize_key_cache(key_cache)); 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;
} }
bool sys_var_key_cache_block_size::update(THD *thd, set_var *var)
bool sys_var_key_cache_long::update(THD *thd, set_var *var)
{ {
ulong tmp= var->value->val_int(); ulong tmp= var->value->val_int();
LEX_STRING *base_name= &var->base; LEX_STRING *base_name= &var->base;
bool error= 0;
if (!base_name->length) if (!base_name->length)
base_name= &default_key_cache_base; base_name= &default_key_cache_base;
pthread_mutex_lock(&LOCK_global_system_variables);
KEY_CACHE_VAR *key_cache= get_key_cache(base_name); KEY_CACHE_VAR *key_cache= get_key_cache(base_name);
if (!key_cache && !(key_cache= create_key_cache(base_name->str, if (!key_cache && !(key_cache= create_key_cache(base_name->str,
base_name->length))) base_name->length)))
return 1; {
error= 1;
goto end;
}
key_cache->block_size= (ulong) getopt_ull_limit_value(tmp, option_limits); /*
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 (key_cache->cache) *((ulong*) (((char*) key_cache) + offset))=
/* Do not build a new key cache here */
return (bool) (ha_resize_key_cache(key_cache));
return 0;
}
bool sys_var_key_cache_division_limit::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); (ulong) getopt_ull_limit_value(tmp, option_limits);
if (key_cache->cache) /*
/* Do not build a new key cache here */ Don't create a new key cache if it didn't exist
return (bool) (ha_change_key_cache_param(key_cache)); (key_caches are created only when the user sets block_size)
return 0; */
} key_cache->in_init= 1;
bool sys_var_key_cache_age_threshold::update(THD *thd, set_var *var) pthread_mutex_unlock(&LOCK_global_system_variables);
{
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);
if (key_cache->cache) error= (bool) (ha_resize_key_cache(key_cache));
/* Do not build a new key cache here */
return (bool) (ha_change_key_cache_param(key_cache)); pthread_mutex_lock(&LOCK_global_system_variables);
return 0; 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; NAMED_LIST *element;
DBUG_ENTER("delete_elements"); DBUG_ENTER("delete_elements");
while ((element= list->get())) while ((element= list->get()))
{ {
(*free_element)(element->data); (*free_element)(element->name, element->data);
delete element; delete element;
} }
DBUG_VOID_RETURN; 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) static KEY_CACHE_VAR *create_key_cache(const char *name, uint length)
{ {
KEY_CACHE_VAR *key_cache; KEY_CACHE_VAR *key_cache;
DBUG_PRINT("info",("Creating key cache: %.*s length: %d", length, name, DBUG_ENTER("create_key_cache");
length)); DBUG_PRINT("enter",("name: %.*s", length, name));
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 ((key_cache= (KEY_CACHE_VAR*) my_malloc(sizeof(KEY_CACHE_VAR), if (!new NAMED_LIST(&key_caches, name, length, (gptr) key_cache))
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;
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;
} }
} }
else DBUG_RETURN(key_cache);
{
key_cache= &dflt_key_cache_var;
if (!new NAMED_LIST(&key_caches, name, length, (gptr) key_cache))
key_cache= 0;
}
return key_cache;
} }
KEY_CACHE_VAR *get_or_create_key_cache(const char *name, uint length) KEY_CACHE_VAR *get_or_create_key_cache(const char *name, uint length)
{ {
LEX_STRING key_cache_name; LEX_STRING key_cache_name;
KEY_CACHE_VAR *key_cache;
key_cache_name.str= (char *) name; key_cache_name.str= (char *) name;
key_cache_name.length= length; key_cache_name.length= length;
KEY_CACHE_VAR *key_cache= get_key_cache(&key_cache_name); pthread_mutex_lock(&LOCK_global_system_variables);
if (!key_cache) if (!(key_cache= get_key_cache(&key_cache_name)))
key_cache= create_key_cache(name, length); key_cache= create_key_cache(name, length);
pthread_mutex_unlock(&LOCK_global_system_variables);
return key_cache; 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) ha_end_key_cache(key_cache);
my_free(key_cache, MYF(0)); 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); I_List_iterator<NAMED_LIST> it(key_caches);
NAMED_LIST *element; NAMED_LIST *element;
while ((element= it++)) while ((element= it++))
{ {
KEY_CACHE_VAR *key_cache= (KEY_CACHE_VAR *) element->data; KEY_CACHE_VAR *key_cache= (KEY_CACHE_VAR *) element->data;
if (key_cache != &dflt_key_cache_var) func(element->name, key_cache);
func(key_cache);
} }
return 0; return 0;
} }

View File

@ -30,11 +30,6 @@ class set_var;
typedef struct system_variables SV; typedef struct system_variables SV;
extern TYPELIB bool_typelib, delay_key_write_typelib, sql_mode_typelib; 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 enum enum_var_type
{ {
OPT_DEFAULT, OPT_SESSION, OPT_GLOBAL OPT_DEFAULT, OPT_SESSION, OPT_GLOBAL
@ -546,73 +541,40 @@ public:
byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base);
}; };
class sys_var_key_cache_param :public sys_var class sys_var_key_cache_param :public sys_var
{ {
protected: protected:
uint offset; size_t offset;
public: public:
sys_var_key_cache_param(const char *name_arg) sys_var_key_cache_param(const char *name_arg, size_t offset_arg)
:sys_var(name_arg) :sys_var(name_arg), offset(offset_arg)
{ {}
offset= 0;
}
byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); 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 class sys_var_key_buffer_size :public sys_var_key_cache_param
{ {
public: public:
sys_var_key_buffer_size(const char *name_arg) sys_var_key_buffer_size(const char *name_arg)
:sys_var_key_cache_param(name_arg) :sys_var_key_cache_param(name_arg, offsetof(KEY_CACHE_VAR, buff_size))
{ {}
offset= offsetof(KEY_CACHE_VAR, buff_size);
}
bool update(THD *thd, set_var *var); bool update(THD *thd, set_var *var);
SHOW_TYPE type() { return SHOW_LONGLONG; } 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 class sys_var_key_cache_long :public sys_var_key_cache_param
{ {
public: public:
sys_var_key_cache_division_limit(const char *name_arg) sys_var_key_cache_long(const char *name_arg, size_t offset_arg)
:sys_var_key_cache_param(name_arg) :sys_var_key_cache_param(name_arg, offset_arg)
{ {}
offset= offsetof(KEY_CACHE_VAR, division_limit);
}
bool update(THD *thd, set_var *var); bool update(THD *thd, set_var *var);
SHOW_TYPE type() { return SHOW_LONG; } 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
{
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);
}
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) uint name_length_arg, gptr data_arg)
:name_length(name_length_arg), data(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); links->push_back(this);
} }
inline bool cmp(const char *name_cmp, uint length) inline bool cmp(const char *name_cmp, uint length)
@ -792,11 +754,16 @@ public:
{ {
my_free((char*) name, MYF(0)); 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 */ /* updated in sql_acl.cc */
extern sys_var_thd_bool sys_old_passwords; extern sys_var_thd_bool sys_old_passwords;
extern LEX_STRING default_key_cache_base;
/* For sql_yacc */ /* For sql_yacc */
struct sys_var_with_base 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); CHARSET_INFO *get_old_charset_by_name(const char *old_name);
gptr find_named(I_List<NAMED_LIST> *list, const char *name, uint length, gptr find_named(I_List<NAMED_LIST> *list, const char *name, uint length,
NAMED_LIST **found); NAMED_LIST **found);
void delete_elements(I_List<NAMED_LIST> *list, void (*free_element)(gptr));
/* key_cache functions */ /* 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); KEY_CACHE_VAR *get_or_create_key_cache(const char *name, uint length);
void free_key_cache(gptr key_cache); void free_key_cache(const char *name, KEY_CACHE_VAR *key_cache);
bool process_key_caches(int (* func) (KEY_CACHE_VAR *));

View File

@ -299,3 +299,4 @@ character-set=latin2
"catalog", "catalog",
"Query cache failed to set size %lu, new query cache size is %lu", "Query cache failed to set size %lu, new query cache size is %lu",
"Column '%-.64s' cannot be part of FULLTEXT index", "Column '%-.64s' cannot be part of FULLTEXT index",
"Unknown key cache '%-.100s'",

View File

@ -293,3 +293,4 @@ character-set=latin1
"catalog", "catalog",
"Query cache failed to set size %lu, new query cache size is %lu", "Query cache failed to set size %lu, new query cache size is %lu",
"Column '%-.64s' cannot be part of FULLTEXT index", "Column '%-.64s' cannot be part of FULLTEXT index",
"Unknown key cache '%-.100s'",

View File

@ -301,3 +301,4 @@ character-set=latin1
"catalog", "catalog",
"Query cache failed to set size %lu, new query cache size is %lu", "Query cache failed to set size %lu, new query cache size is %lu",
"Column '%-.64s' cannot be part of FULLTEXT index", "Column '%-.64s' cannot be part of FULLTEXT index",
"Unknown key cache '%-.100s'",

View File

@ -290,3 +290,4 @@ character-set=latin1
"catalog", "catalog",
"Query cache failed to set size %lu, new query cache size is %lu", "Query cache failed to set size %lu, new query cache size is %lu",
"Column '%-.64s' cannot be part of FULLTEXT index", "Column '%-.64s' cannot be part of FULLTEXT index",
"Unknown key cache '%-.100s'",

View File

@ -295,3 +295,4 @@ character-set=latin7
"catalog", "catalog",
"Query cache failed to set size %lu, new query cache size is %lu", "Query cache failed to set size %lu, new query cache size is %lu",
"Column '%-.64s' cannot be part of FULLTEXT index", "Column '%-.64s' cannot be part of FULLTEXT index",
"Unknown key cache '%-.100s'",

View File

@ -290,3 +290,4 @@ character-set=latin1
"catalog", "catalog",
"Query cache failed to set size %lu, new query cache size is %lu", "Query cache failed to set size %lu, new query cache size is %lu",
"Column '%-.64s' cannot be part of FULLTEXT index", "Column '%-.64s' cannot be part of FULLTEXT index",
"Unknown key cache '%-.100s'",

View File

@ -302,3 +302,4 @@ character-set=latin1
"catalog", "catalog",
"Query cache failed to set size %lu, new query cache size is %lu", "Query cache failed to set size %lu, new query cache size is %lu",
"Column '%-.64s' cannot be part of FULLTEXT index", "Column '%-.64s' cannot be part of FULLTEXT index",
"Unknown key cache '%-.100s'",

View File

@ -290,3 +290,4 @@ character-set=greek
"catalog", "catalog",
"Query cache failed to set size %lu, new query cache size is %lu", "Query cache failed to set size %lu, new query cache size is %lu",
"Column '%-.64s' cannot be part of FULLTEXT index", "Column '%-.64s' cannot be part of FULLTEXT index",
"Unknown key cache '%-.100s'",

View File

@ -292,3 +292,4 @@ character-set=latin2
"catalog", "catalog",
"Query cache failed to set size %lu, new query cache size is %lu", "Query cache failed to set size %lu, new query cache size is %lu",
"Column '%-.64s' cannot be part of FULLTEXT index", "Column '%-.64s' cannot be part of FULLTEXT index",
"Unknown key cache '%-.100s'",

View File

@ -290,3 +290,4 @@ character-set=latin1
"catalog", "catalog",
"Query cache failed to set size %lu, new query cache size is %lu", "Query cache failed to set size %lu, new query cache size is %lu",
"Column '%-.64s' cannot be part of FULLTEXT index", "Column '%-.64s' cannot be part of FULLTEXT index",
"Unknown key cache '%-.100s'",

View File

@ -292,3 +292,4 @@ character-set=ujis
"catalog", "catalog",
"Query cache failed to set size %lu, new query cache size is %lu", "Query cache failed to set size %lu, new query cache size is %lu",
"Column '%-.64s' cannot be part of FULLTEXT index", "Column '%-.64s' cannot be part of FULLTEXT index",
"Unknown key cache '%-.100s'",

View File

@ -290,3 +290,4 @@ character-set=euckr
"catalog", "catalog",
"Query cache failed to set size %lu, new query cache size is %lu", "Query cache failed to set size %lu, new query cache size is %lu",
"Column '%-.64s' cannot be part of FULLTEXT index", "Column '%-.64s' cannot be part of FULLTEXT index",
"Unknown key cache '%-.100s'",

Some files were not shown because too many files have changed in this diff Show More