This commit is contained in:
monty@mashka.mysql.fi 2003-11-18 13:51:48 +02:00
commit e5d75fb984
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"
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"

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);
if (!mysql_real_connect(&mysql, host, user, password,
database, opt_mysql_port, opt_mysql_unix_port,
connect_flag | CLIENT_MULTI_QUERIES))
connect_flag | CLIENT_MULTI_STATEMENTS))
{
if (!silent ||
(mysql_errno(&mysql) != CR_CONN_HOST_ERROR &&

View file

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

View file

@ -27,5 +27,9 @@
#define pthread_mutex_lock(A)
#define pthread_mutex_unlock(A)
#define pthread_mutex_destroy(A)
#define my_rwlock_init(A,B)
#define rw_rdlock(A)
#define rw_wrlock(A)
#define rw_unlock(A)
#define rwlock_destroy(A)
#endif

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
it under the terms of the GNU General Public License as published by
@ -111,6 +111,7 @@ extern int NEAR my_errno; /* Last error in mysys */
#define MY_WAIT_FOR_USER_TO_FIX_PANIC 60 /* in seconds */
#define MY_WAIT_GIVE_USER_A_MESSAGE 10 /* Every 10 times of prev */
#define MIN_COMPRESS_LENGTH 50 /* Don't compress small bl. */
#define DFLT_INIT_HITS 3
/* root_alloc flags */
#define MY_KEEP_PREALLOC 1
@ -510,13 +511,13 @@ typedef struct st_key_cache* KEY_CACHE_HANDLE;
/* Key cache variable structure */
/*
The structure contains the parameters of a key cache that can
be set and undated by regular set global statements.
It also contains read-only statistics parameters.
If the corresponding key cache data structure has been already
created the variable contains the key cache handle.
The variables are put into a named list called key_caches.
At present the variables are only added to this list.
The structure contains the parameters of a key cache that can
be set and undated by regular set global statements.
It also contains read-only statistics parameters.
If the corresponding key cache data structure has been already
created the variable contains the key cache handle.
The variables are put into a named list called key_caches.
At present the variables are only added to this list.
*/
typedef struct st_key_cache_var
{
@ -532,16 +533,16 @@ typedef struct st_key_cache_var
ulong cache_r_requests; /* number of read requests (read hits) */
ulong cache_read; /* number of reads from files to the cache */
int blocks; /* max number of blocks in the cache */
my_bool in_init; /* Set to 1 in MySQL during init/resize */
struct st_key_cache_asmt *assign_list; /* list of assignments to the cache */
int assignments; /* number of not completed assignments */
void (*action)(void *); /* optional call back function */
void *extra_info; /* ptr to extra info */
} KEY_CACHE_VAR;
#define DEFAULT_KEY_CACHE_NAME "default"
extern KEY_CACHE_HANDLE *dflt_keycache;
extern KEY_CACHE_VAR dflt_key_cache_var;
#define DFLT_INIT_HITS 3
#include <my_alloc.h>
@ -701,7 +702,15 @@ extern int key_cache_write(KEY_CACHE_HANDLE keycache,
uint block_length,int force_write);
extern int flush_key_blocks(KEY_CACHE_HANDLE keycache,
int file, enum flush_type type);
extern void end_key_cache(KEY_CACHE_HANDLE *pkeycache,my_bool cleanup);
extern void end_key_cache(KEY_CACHE_HANDLE keycache, my_bool cleanup);
extern my_bool multi_keycache_init(void);
extern void multi_keycache_free(void);
extern KEY_CACHE_HANDLE *multi_key_cache_search(byte *key, uint length);
extern my_bool multi_key_cache_set(const byte *key, uint length,
KEY_CACHE_HANDLE *key_cache);
extern void multi_key_cache_change(KEY_CACHE_HANDLE *old_data,
KEY_CACHE_HANDLE *new_data);
extern sig_handler my_set_alarm_variable(int signo);
extern void my_string_ptr_sort(void *base,uint items,size_s size);
extern void radixsort_for_str_ptr(uchar* base[], uint number_of_elements,

View file

@ -324,7 +324,7 @@ typedef struct st_mi_check_param
sort_buffer_length,sort_key_blocks;
uint out_flag,warning_printed,error_printed,verbose;
uint opt_sort_key,total_files,max_level;
uint testflag;
uint testflag, key_cache_block_size;
uint8 language;
my_bool using_global_keycache, opt_lock_memory, opt_follow_links;
my_bool retry_repair, force_sort, calc_checksum;
@ -388,7 +388,6 @@ int change_to_newfile(const char * filename, const char * old_ext,
int lock_file(MI_CHECK *param, File file, my_off_t start, int lock_type,
const char *filetype, const char *filename);
void lock_memory(MI_CHECK *param);
int flush_blocks(MI_CHECK *param, File file);
void update_auto_increment_key(MI_CHECK *param, MI_INFO *info,
my_bool repair);
int update_state_info(MI_CHECK *param, MI_INFO *info,uint update);
@ -408,9 +407,10 @@ my_bool mi_test_if_sort_rep(MI_INFO *info, ha_rows rows, ulonglong key_map,
int mi_init_bulk_insert(MI_INFO *info, ulong cache_size, ha_rows rows);
void mi_flush_bulk_insert(MI_INFO *info, uint inx);
void mi_end_bulk_insert(MI_INFO *info);
int mi_assign_to_keycache(MI_INFO *info, ulonglong key_map,
KEY_CACHE_VAR *key_cache,
pthread_mutex_t *assign_lock);
int mi_assign_to_key_cache(MI_INFO *info, ulonglong key_map,
KEY_CACHE_VAR *key_cache);
void mi_change_key_cache(KEY_CACHE_VAR *old_key_cache,
KEY_CACHE_VAR *new_key_cache);
int mi_preload(MI_INFO *info, ulonglong key_map, my_bool ignore_leaves);
#ifdef __cplusplus

View file

@ -411,6 +411,9 @@ int STDCALL mysql_dump_debug_info(MYSQL *mysql);
int STDCALL mysql_refresh(MYSQL *mysql,
unsigned int refresh_options);
int STDCALL mysql_kill(MYSQL *mysql,unsigned long pid);
int STDCALL mysql_set_server_option(MYSQL *mysql,
enum enum_mysql_set_option
option);
int STDCALL mysql_ping(MYSQL *mysql);
const char * STDCALL mysql_stat(MYSQL *mysql);
const char * STDCALL mysql_get_server_info(MYSQL *mysql);

View file

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

View file

@ -302,4 +302,5 @@
#define ER_WRONG_NAME_FOR_CATALOG 1283
#define ER_WARN_QC_RESIZE 1284
#define ER_BAD_FT_COLUMN 1285
#define ER_ERROR_MESSAGES 286
#define ER_UNKNOWN_KEY_CACHE 1286
#define ER_ERROR_MESSAGES 287

View file

@ -1629,9 +1629,6 @@ NetWare. */
srv_file_per_table = srv_file_per_table_original_value;
fprintf(stderr,
"TODO: make sure MySQL sets field->query_id right in prepare/execute\n");
return((int) DB_SUCCESS);
}

View file

@ -1088,10 +1088,20 @@ mysql_refresh(MYSQL *mysql,uint options)
int STDCALL
mysql_kill(MYSQL *mysql,ulong pid)
{
char buff[12];
char buff[4];
DBUG_ENTER("mysql_kill");
int4store(buff,pid);
DBUG_RETURN(simple_command(mysql,COM_PROCESS_KILL,buff,4,0));
DBUG_RETURN(simple_command(mysql,COM_PROCESS_KILL,buff,sizeof(buff),0));
}
int STDCALL
mysql_set_server_option(MYSQL *mysql, enum enum_mysql_set_option option)
{
char buff[2];
DBUG_ENTER("mysql_set_server_option");
int2store(buff, (uint) option);
DBUG_RETURN(simple_command(mysql, COM_SET_OPTION, buff, sizeof(buff), 0));
}

View file

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

View file

@ -225,7 +225,8 @@ FT_INFO *ft_init_nlq_search(MI_INFO *info, uint keynr, byte *query,
if (flags & FT_EXPAND && ft_query_expansion_limit)
{
QUEUE best;
init_queue(&best,ft_query_expansion_limit,0,0, &FT_DOC_cmp, 0);
init_queue(&best,ft_query_expansion_limit,0,0, (queue_compare) &FT_DOC_cmp,
0);
tree_walk(&aio.dtree, (tree_walk_action) &walk_and_push,
&best, left_root_right);
while (best.elements)

View file

@ -53,13 +53,17 @@ const struct _ft_vft _ft_vft_boolean = {
ft_boolean_get_relevance, ft_boolean_reinit_search
};
FT_INFO *ft_init_search(uint flags, void *info, uint keynr,
byte *query, uint query_len, byte *record)
{
FT_INFO *res;
if (flags & FT_BOOL)
ft_init_boolean_search((MI_INFO *)info, keynr, query, query_len);
res= ft_init_boolean_search((MI_INFO *)info, keynr, query, query_len);
else
ft_init_nlq_search((MI_INFO *)info, keynr, query, query_len, flags, record);
res= ft_init_nlq_search((MI_INFO *)info, keynr, query, query_len, flags,
record);
return res;
}
const char *ft_stopword_file = 0;

View file

@ -77,6 +77,7 @@ void myisamchk_init(MI_CHECK *param)
param->tmpfile_createflag=O_RDWR | O_TRUNC | O_EXCL;
param->myf_rw=MYF(MY_NABP | MY_WME | MY_WAIT_IF_FULL);
param->start_check_pos=0;
param->key_cache_block_size= KEY_CACHE_BLOCK_SIZE;
}
/* Check the status flags for the table */
@ -241,7 +242,7 @@ static int check_k_link(MI_CHECK *param, register MI_INFO *info, uint nr)
if (next_link > info->state->key_file_length ||
next_link & (info->s->blocksize-1))
DBUG_RETURN(1);
if (!(buff=key_cache_read(*info->s->keycache,
if (!(buff=key_cache_read(*info->s->key_cache,
info->s->kfile, next_link, DFLT_INIT_HITS,
(byte*) info->buff,
myisam_block_size, block_size, 1)))
@ -272,7 +273,7 @@ int chk_size(MI_CHECK *param, register MI_INFO *info)
if (!(param->testflag & T_SILENT)) puts("- check file-size");
flush_key_blocks(*info->s->keycache,
flush_key_blocks(*info->s->key_cache,
info->s->kfile, FLUSH_FORCE_WRITE); /* If called externally */
size=my_seek(info->s->kfile,0L,MY_SEEK_END,MYF(0));
@ -1142,8 +1143,8 @@ int mi_repair(MI_CHECK *param, register MI_INFO *info,
param->testflag|=T_REP; /* for easy checking */
if (!param->using_global_keycache)
VOID(init_key_cache(dflt_keycache,dflt_key_cache_var.block_size,
param->use_buffers,&dflt_key_cache_var));
VOID(init_key_cache(dflt_keycache, param->key_cache_block_size,
param->use_buffers, &dflt_key_cache_var));
if (init_io_cache(&param->read_cache,info->dfile,
(uint) param->read_buffer_length,
@ -1364,7 +1365,7 @@ err:
VOID(end_io_cache(&param->read_cache));
info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
VOID(end_io_cache(&info->rec_cache));
got_error|=flush_blocks(param,share->kfile);
got_error|=flush_blocks(param, *share->key_cache, share->kfile);
if (!got_error && param->testflag & T_UNPACK)
{
share->state.header.options[0]&= (uchar) ~HA_OPTION_COMPRESS_RECORD;
@ -1500,15 +1501,15 @@ void lock_memory(MI_CHECK *param __attribute__((unused)))
/* Flush all changed blocks to disk */
int flush_blocks(MI_CHECK *param, File file)
int flush_blocks(MI_CHECK *param, KEY_CACHE_HANDLE key_cache, File file)
{
if (flush_key_blocks(*dflt_keycache,file,FLUSH_RELEASE))
if (flush_key_blocks(key_cache, file, FLUSH_RELEASE))
{
mi_check_print_error(param,"%d when trying to write bufferts",my_errno);
return(1);
}
if (!param->using_global_keycache)
end_key_cache(dflt_keycache,1);
end_key_cache(key_cache,1);
return 0;
} /* flush_blocks */
@ -1563,7 +1564,7 @@ int mi_sort_index(MI_CHECK *param, register MI_INFO *info, my_string name)
}
/* Flush key cache for this file if we are calling this outside myisamchk */
flush_key_blocks(*share->keycache,share->kfile, FLUSH_IGNORE_CHANGED);
flush_key_blocks(*share->key_cache,share->kfile, FLUSH_IGNORE_CHANGED);
share->state.version=(ulong) time((time_t*) 0);
old_state= share->state; /* save state if not stored */
@ -1873,7 +1874,7 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info,
Flush key cache for this file if we are calling this outside
myisamchk
*/
flush_key_blocks(*share->keycache,share->kfile, FLUSH_IGNORE_CHANGED);
flush_key_blocks(*share->key_cache,share->kfile, FLUSH_IGNORE_CHANGED);
/* Clear the pointers to the given rows */
for (i=0 ; i < share->base.keys ; i++)
share->state.key_root[i]= HA_OFFSET_ERROR;
@ -1883,7 +1884,7 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info,
}
else
{
if (flush_key_blocks(*share->keycache,share->kfile, FLUSH_FORCE_WRITE))
if (flush_key_blocks(*share->key_cache,share->kfile, FLUSH_FORCE_WRITE))
goto err;
key_map= ~key_map; /* Create the missing keys */
}
@ -2075,7 +2076,7 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info,
memcpy( &share->state.state, info->state, sizeof(*info->state));
err:
got_error|= flush_blocks(param,share->kfile);
got_error|= flush_blocks(param, *share->key_cache, share->kfile);
VOID(end_io_cache(&info->rec_cache));
if (!got_error)
{
@ -2236,7 +2237,7 @@ int mi_repair_parallel(MI_CHECK *param, register MI_INFO *info,
Flush key cache for this file if we are calling this outside
myisamchk
*/
flush_key_blocks(*share->keycache,share->kfile, FLUSH_IGNORE_CHANGED);
flush_key_blocks(*share->key_cache,share->kfile, FLUSH_IGNORE_CHANGED);
/* Clear the pointers to the given rows */
for (i=0 ; i < share->base.keys ; i++)
share->state.key_root[i]= HA_OFFSET_ERROR;
@ -2246,7 +2247,7 @@ int mi_repair_parallel(MI_CHECK *param, register MI_INFO *info,
}
else
{
if (flush_key_blocks(*share->keycache,share->kfile, FLUSH_FORCE_WRITE))
if (flush_key_blocks(*share->key_cache,share->kfile, FLUSH_FORCE_WRITE))
goto err;
key_map= ~key_map; /* Create the missing keys */
}
@ -2482,7 +2483,7 @@ int mi_repair_parallel(MI_CHECK *param, register MI_INFO *info,
memcpy(&share->state.state, info->state, sizeof(*info->state));
err:
got_error|= flush_blocks(param,share->kfile);
got_error|= flush_blocks(param, *share->key_cache, share->kfile);
VOID(end_io_cache(&info->rec_cache));
if (!got_error)
{
@ -3087,7 +3088,8 @@ int sort_write_record(MI_SORT_PARAM *sort_param)
(info->state->records % WRITE_COUNT) == 0)
{
char llbuff[22];
printf("%s\r", llstr(info->state->records,llbuff)); VOID(fflush(stdout));
printf("%s\r", llstr(info->state->records,llbuff));
VOID(fflush(stdout));
}
}
DBUG_RETURN(0);

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)
{
const byte *pos;
const byte *end;
ulong length;
switch (rec->type) {
case FIELD_BLOB:

View file

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

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
since it was locked then there may be key blocks in the key cache
*/
flush_key_blocks(*share->keycache, share->kfile, FLUSH_IGNORE_CHANGED);
flush_key_blocks(*share->key_cache, share->kfile, FLUSH_IGNORE_CHANGED);
if (my_chsize(info->dfile, 0, 0, MYF(MY_WME)) ||
my_chsize(share->kfile, share->base.keystart, 0, MYF(MY_WME)) )
goto err;

View file

@ -329,7 +329,7 @@ int mi_extra(MI_INFO *info, enum ha_extra_function function, void *extra_arg)
break;
case HA_EXTRA_FLUSH:
if (!share->temporary)
flush_key_blocks(*share->keycache,share->kfile,FLUSH_KEEP);
flush_key_blocks(*share->key_cache, share->kfile, FLUSH_KEEP);
#ifdef HAVE_PWRITE
_mi_decrement_open_count(info);
#endif
@ -362,9 +362,6 @@ int mi_extra(MI_INFO *info, enum ha_extra_function function, void *extra_arg)
case HA_EXTRA_PRELOAD_BUFFER_SIZE:
info->preload_buff_size= *((ulong *) extra_arg);
break;
case HA_EXTRA_SET_KEY_CACHE:
share->reg_keycache= share->keycache= (KEY_CACHE_HANDLE *) extra_arg;
break;
case HA_EXTRA_KEY_CACHE:
case HA_EXTRA_NO_KEY_CACHE:
default:

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
it under the terms of the GNU General Public License as published by
@ -20,88 +20,136 @@
#include "myisamdef.h"
/*
Assign pages of the index file for a table to a key cache
SYNOPSIS
mi_assign_to_keycache()
mi_assign_to_key_cache()
info open table
map map of indexes to assign to the key cache
key_map map of indexes to assign to the key cache
key_cache_ptr pointer to the key cache handle
assign_lock Mutex to lock during assignment
RETURN VALUE
0 if a success. error code - otherwise.
PREREQUESTS
One must have a READ lock or a WRITE lock on the table when calling
the function to ensure that there is no other writers to it.
NOTES.
The caller must also ensure that one doesn't call this function from
two different threads with the same table.
NOTES
At present pages for all indexes must be assigned to the same key cache.
In future only pages for indexes specified in the key_map parameter
of the table will be assigned to the specified key cache.
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;
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);
if (!(extra_info= (ASSIGN_EXTRA_INFO *) key_cache->extra_info))
/*
First flush all blocks for the table in the old key cache.
This is to ensure that the disk is consistent with the data pages
in memory (which may not be the case if the table uses delayed_key_write)
Note that some other read thread may still fill in the key cache with
new blocks during this call and after, but this doesn't matter as
all threads will start using the new key cache for their next call to
myisam library and we know that there will not be any changed blocks
in the old key cache.
*/
if (flush_key_blocks(*share->key_cache, share->kfile, FLUSH_REMOVE))
{
if (!(extra_info= (ASSIGN_EXTRA_INFO*) my_malloc(sizeof(ASSIGN_EXTRA_INFO),
MYF(MY_WME | MY_ZEROFILL))))
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
key_cache->extra_info= extra_info;
key_cache->action= remove_key_cache_assign;
extra_info->lock= assign_lock;
}
key_cache->assignments++;
pthread_mutex_unlock(assign_lock);
if (!(info->lock_type == F_WRLCK && share->w_locks))
{
if (flush_key_blocks(*share->keycache, share->kfile, FLUSH_REMOVE))
{
error=my_errno;
mi_mark_crashed(info); /* Mark that table must be checked */
}
share->keycache= &key_cache->cache;
}
else
{
extra_info->waiting_thread= my_thread_var;
error= my_errno;
mi_mark_crashed(info); /* Mark that table must be checked */
}
/*
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);
}
/*
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;
MYISAM_SHARE *share=info->s;
uint flag;
uint switch_fl= 0;
DBUG_ENTER("mi_lock_database");
DBUG_PRINT("info",("lock_type: %d", lock_type));
@ -61,21 +60,13 @@ int mi_lock_database(MI_INFO *info, int lock_type)
else
count= --share->w_locks;
--share->tot_locks;
/*
During a key cache reassignment the current and registered
key caches for the table are different.
*/
if (info->lock_type == F_WRLCK && !share->w_locks &&
((switch_fl= share->keycache != share->reg_keycache) ||
!share->delay_key_write) &&
flush_key_blocks(*share->keycache, share->kfile,
switch_fl ? FLUSH_REMOVE : FLUSH_KEEP))
!share->delay_key_write && flush_key_blocks(*share->key_cache,
share->kfile,FLUSH_KEEP))
{
error=my_errno;
mi_mark_crashed(info); /* Mark that table must be checked */
}
if (switch_fl)
share->keycache= share->reg_keycache;
if (info->opt_flag & (READ_CACHE_USED | WRITE_CACHE_USED))
{
if (end_io_cache(&info->rec_cache))
@ -398,7 +389,7 @@ int _mi_test_if_changed(register MI_INFO *info)
{ /* Keyfile has changed */
DBUG_PRINT("info",("index file changed"));
if (share->state.process != share->this_process)
VOID(flush_key_blocks(*share->keycache,share->kfile,FLUSH_RELEASE));
VOID(flush_key_blocks(*share->key_cache, share->kfile, FLUSH_RELEASE));
share->last_process=share->state.process;
info->last_unique= share->state.unique;
info->last_loop= share->state.update_count;

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.key_root=key_root;
share_buff.state.key_del=key_del;
share_buff.key_cache= multi_key_cache_search(name_buff, strlen(name_buff));
if ((kfile=my_open(name_buff,(open_mode=O_RDWR) | O_SHARE,MYF(0))) < 0)
{
@ -293,6 +294,7 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
(char*) key_del, (sizeof(my_off_t) *
share->state.header.max_block_size));
strmov(share->unique_file_name, name_buff);
share->unique_name_length= strlen(name_buff);
strmov(share->index_file_name, index_name);
strmov(share->data_file_name, data_name);

View file

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

View file

@ -48,7 +48,7 @@ int mi_panic(enum ha_panic_function flag)
if (info->s->options & HA_OPTION_READ_ONLY_DATA)
break;
#endif
if (flush_key_blocks(*info->s->keycache,info->s->kfile,FLUSH_RELEASE))
if (flush_key_blocks(*info->s->key_cache, info->s->kfile, FLUSH_RELEASE))
error=my_errno;
if (info->opt_flag & WRITE_CACHE_USED)
if (flush_io_cache(&info->rec_cache))

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

View file

@ -50,7 +50,7 @@ int main(int argc,char *argv[])
MY_INIT(argv[0]);
my_init();
if (key_cacheing)
init_key_cache(dflt_keycache,512,IO_SIZE*16,0);
init_key_cache(dflt_keycache,KEY_CACHE_BLOCK_SIZE,IO_SIZE*16,0);
get_options(argc,argv);
exit(run_test("test1"));

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,
create_flag=0;
static ulong key_cache_size=IO_SIZE*16;
static uint key_cache_block_size=IO_SIZE;
static uint key_cache_block_size= KEY_CACHE_BLOCK_SIZE;
static uint keys=MYISAM_KEYS,recant=1000;
static uint use_blob=0;
@ -274,9 +274,9 @@ int main(int argc, char *argv[])
puts("got error from mi_extra(HA_EXTRA_NO_CACHE)");
goto end;
}
if (key_cacheing)
resize_key_cache(dflt_keycache,key_cache_block_size,key_cache_size*2);
}
if (key_cacheing)
resize_key_cache(dflt_keycache,key_cache_block_size,key_cache_size*2);
if (!silent)
printf("- Delete\n");
@ -829,7 +829,7 @@ reads: %10lu\n",
my_cache_r_requests, my_cache_read);
#endif
}
end_key_cache(dflt_keycache,1);
end_key_cache(*dflt_keycache,1);
if (blob_buffer)
my_free(blob_buffer,MYF(0));
my_end(silent ? MY_CHECK_ERROR : MY_CHECK_ERROR | MY_GIVE_INFO);

View file

@ -177,7 +177,7 @@ void start_test(int id)
exit(1);
}
if (key_cacheing && rnd(2) == 0)
init_key_cache(dflt_keycache,512,65536L,0);
init_key_cache(dflt_keycache, KEY_CACHE_BLOCK_SIZE, 65536L,0);
printf("Process %d, pid: %d\n",id,getpid()); fflush(stdout);
for (error=i=0 ; i < tests && !error; i++)

View file

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

View file

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

View file

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

View file

@ -575,7 +575,7 @@ show_failed_diff ()
$DIFF -c $result_file $reject_file
echo "-------------------------------------------------------"
echo "Please follow the instructions outlined at"
echo "http://www.mysql.com/doc/R/e/Reporting_mysqltest_bugs.html"
echo "http://www.mysql.com/doc/en/Reporting_mysqltest_bugs.html"
echo "to find the reason to this problem and how to report this."
fi
}
@ -1311,7 +1311,7 @@ run_testcase ()
show_failed_diff $tname
$ECHO
if [ x$FORCE != x1 ] ; then
$ECHO "Aborting. To continue, re-run with '--force'."
$ECHO "Aborting becasue $tname failed. To continue, re-run with '--force'."
$ECHO
if [ -z "$DO_GDB" ] && [ -z "$USE_RUNNING_SERVER" ] && [ -z "$DO_DDD" ]
then

View file

@ -319,6 +319,29 @@ alter table t1 change a a char(10) character set koi8r;
select a,hex(a) from t1;
a hex(a)
ÔĹÓÔ D4C5D3D4
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` char(10) character set koi8r default NULL
) TYPE=MyISAM DEFAULT CHARSET=latin1
alter table t1 DEFAULT CHARACTER SET latin1;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` char(10) character set koi8r default NULL
) TYPE=MyISAM DEFAULT CHARSET=latin1
alter table t1 CHARACTER SET latin1;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` char(10) default NULL
) TYPE=MyISAM DEFAULT CHARSET=latin1
alter table t1 DEFAULT CHARACTER SET cp1251;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` char(10) character set latin1 default NULL
) TYPE=MyISAM DEFAULT CHARSET=cp1251
drop table t1;
CREATE TABLE t1 (
Host varchar(16) binary NOT NULL default '',

View file

@ -103,7 +103,7 @@ t1 CREATE TABLE `t1` (
`c6` char(3) default NULL,
`c7` double(3,1) default NULL,
`c8` double(3,1) default NULL
) TYPE=MyISAM CHARSET=latin1
) TYPE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
SELECT CASE
WHEN 1
@ -150,5 +150,5 @@ t1 CREATE TABLE `t1` (
`COALESCE(1,'1')` char(1) NOT NULL default '',
`COALESCE(1.1,'1')` char(3) NOT NULL default '',
`COALESCE('a' COLLATE latin1_bin,'b')` char(1) character set latin1 collate latin1_bin NOT NULL default ''
) TYPE=MyISAM CHARSET=latin1
) TYPE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -6,7 +6,7 @@ SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` char(10) character set cp1251 default NULL
) TYPE=MyISAM CHARSET=latin1
) TYPE=MyISAM DEFAULT CHARSET=latin1
SELECT a FROM t1;
a
ÐÒÏÂÁ
@ -25,7 +25,7 @@ SHOW CREATE TABLE
Table Create Table
ÔÁÂÌÉÃÁ CREATE TABLE `ÔÁÂÌÉÃÁ` (
`ÐÏÌÅ` char(32) character set koi8r NOT NULL default '' COMMENT 'ËÏÍÍÅÎÔÁÒÉÊ ÐÏÌÑ'
) TYPE=MyISAM CHARSET=latin1 COMMENT='ËÏÍÍÅÎÔÁÒÉÊ ÔÁÂÌÉÃÙ'
) TYPE=MyISAM DEFAULT CHARSET=latin1 COMMENT='ËÏÍÍÅÎÔÁÒÉÊ ÔÁÂÌÉÃÙ'
SHOW FIELDS FROM ÔÁÂÌÉÃÁ;
Field Type Null Key Default Extra
ÐÏÌÅ char(32)
@ -37,7 +37,7 @@ SHOW CREATE TABLE
Table Create Table
òàáëèöà CREATE TABLE `òàáëèöà` (
`ïîëå` char(32) character set koi8r NOT NULL default '' COMMENT 'êîììåíòàðèé ïîëÿ'
) TYPE=MyISAM CHARSET=latin1 COMMENT='êîììåíòàðèé òàáëèöû'
) TYPE=MyISAM DEFAULT CHARSET=latin1 COMMENT='êîììåíòàðèé òàáëèöû'
SHOW FIELDS FROM òàáëèöà;
Field Type Null Key Default Extra
ïîëå char(32)
@ -49,7 +49,7 @@ SHOW CREATE TABLE таблица;
Table Create Table
таблица CREATE TABLE `таблица` (
`поле` char(32) character set koi8r NOT NULL default '' COMMENT 'комментарий полÑ<C2BB>'
) TYPE=MyISAM CHARSET=latin1 COMMENT='комментарий таблицы'
) TYPE=MyISAM DEFAULT CHARSET=latin1 COMMENT='комментарий таблицы'
SHOW FIELDS FROM таблица;
Field Type Null Key Default Extra
поле char(32)

View file

@ -45,7 +45,7 @@ Table Create Table
t1 CREATE TABLE `t1` (
`l` char(10) character set ucs2 NOT NULL default '',
`r` char(10) character set ucs2 NOT NULL default ''
) TYPE=MyISAM CHARSET=latin1
) TYPE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
SET NAMES koi8r;
SET character_set_connection=ucs2;

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);
insert into t1 values (NULL, 'a', 1), (NULL, 'b', 2), (NULL, 'c', 3), (NULL, 'd', 4), (NULL, 'e', 5), (NULL, 'f', 6), (NULL, 'g', 7), (NULL, 'h', 8), (NULL, 'i', 9);
insert into t2 values (1, 100), (1, 101), (1, 102), (2, 100), (2, 103), (2, 104), (3, 101), (3, 102), (3, 105);
SELECT d.pla_id, m2.mat_id FROM t1 m2 INNER JOIN (SELECT mp.pla_id, MIN(m1.matintnum) AS matintnum FROM t2 mp INNER JOIN t1 m1 ON mp.mat_id=m1.mat_id GROUP BY mp.pla_id) d ON d.matintnum=m2.matintnum;
SELECT STRAIGHT_JOIN d.pla_id, m2.mat_id FROM t1 m2 INNER JOIN (SELECT mp.pla_id, MIN(m1.matintnum) AS matintnum FROM t2 mp INNER JOIN t1 m1 ON mp.mat_id=m1.mat_id GROUP BY mp.pla_id) d ON d.matintnum=m2.matintnum;
pla_id mat_id
100 1
101 1
@ -172,7 +172,7 @@ pla_id mat_id
103 2
104 2
105 3
SELECT d.pla_id, m2.test FROM t1 m2 INNER JOIN (SELECT mp.pla_id, MIN(m1.matintnum) AS matintnum FROM t2 mp INNER JOIN t1 m1 ON mp.mat_id=m1.mat_id GROUP BY mp.pla_id) d ON d.matintnum=m2.matintnum;
SELECT STRAIGHT_JOIN d.pla_id, m2.test FROM t1 m2 INNER JOIN (SELECT mp.pla_id, MIN(m1.matintnum) AS matintnum FROM t2 mp INNER JOIN t1 m1 ON mp.mat_id=m1.mat_id GROUP BY mp.pla_id) d ON d.matintnum=m2.matintnum;
pla_id test
100 1
101 1
@ -180,13 +180,13 @@ pla_id test
103 2
104 2
105 3
explain SELECT d.pla_id, m2.mat_id FROM t1 m2 INNER JOIN (SELECT mp.pla_id, MIN(m1.matintnum) AS matintnum FROM t2 mp INNER JOIN t1 m1 ON mp.mat_id=m1.mat_id GROUP BY mp.pla_id) d ON d.matintnum=m2.matintnum;
explain SELECT STRAIGHT_JOIN d.pla_id, m2.mat_id FROM t1 m2 INNER JOIN (SELECT mp.pla_id, MIN(m1.matintnum) AS matintnum FROM t2 mp INNER JOIN t1 m1 ON mp.mat_id=m1.mat_id GROUP BY mp.pla_id) d ON d.matintnum=m2.matintnum;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY m2 ALL NULL NULL NULL NULL 9
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 6 Using where
2 DERIVED mp ALL NULL NULL NULL NULL 9 Using temporary; Using filesort
2 DERIVED m2 index NULL PRIMARY 3 NULL 9 Using index
explain SELECT d.pla_id, m2.test FROM t1 m2 INNER JOIN (SELECT mp.pla_id, MIN(m1.matintnum) AS matintnum FROM t2 mp INNER JOIN t1 m1 ON mp.mat_id=m1.mat_id GROUP BY mp.pla_id) d ON d.matintnum=m2.matintnum;
explain SELECT STRAIGHT_JOIN d.pla_id, m2.test FROM t1 m2 INNER JOIN (SELECT mp.pla_id, MIN(m1.matintnum) AS matintnum FROM t2 mp INNER JOIN t1 m1 ON mp.mat_id=m1.mat_id GROUP BY mp.pla_id) d ON d.matintnum=m2.matintnum;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY m2 ALL NULL NULL NULL NULL 9
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 6 Using where

View file

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

View file

@ -539,7 +539,7 @@ t1 CREATE TABLE `t1` (
`substring(_latin2'ab',1)` char(2) character set latin2 NOT NULL default '',
`insert(_latin2'abcd',2,3,_latin2'ef')` char(6) character set latin2 NOT NULL default '',
`replace(_latin2'abcd',_latin2'b',_latin2'B')` char(4) character set latin2 NOT NULL default ''
) TYPE=MyISAM CHARSET=latin1
) TYPE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
select SUBSTR('abcdefg',3,2);
SUBSTR('abcdefg',3,2)

View file

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

View file

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

View file

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

View file

@ -1,3 +1,4 @@
drop table if exists t1, t2, t3;
SET @save_key_buffer=@@key_buffer_size;
SELECT @@key_buffer_size, @@small.key_buffer_size;
@@key_buffer_size @@small.key_buffer_size
@ -74,15 +75,15 @@ select @@keycache1.key_buffer_size;
0
select @@keycache1.key_cache_block_size;
@@keycache1.key_cache_block_size
0
2048
select @@key_buffer_size;
@@key_buffer_size
2097152
select @@key_cache_block_size;
@@key_cache_block_size
1024
drop table if exists t1, t2;
create table t1 (p int primary key, a char(10));
set global keycache1.key_buffer_size=1024*1024;
create table t1 (p int primary key, a char(10)) delay_key_write=1;
create table t2 (p int primary key, i int, a char(10), key k1(i), key k2(a));
insert into t1 values (1, 'qqqq'), (11, 'yyyy');
insert into t2 values (1, 1, 'qqqq'), (2, 1, 'pppp'),
@ -99,7 +100,7 @@ p i a
4 3 zzzz
update t1 set p=2 where p=1;
update t2 set i=2 where i=1;
cache index t1 keys in keycache1;
cache index t1 keys (`primary`) in keycache1;
Table Op Msg_type Msg_text
test.t1 assign_to_keycache status OK
explain select p from t1;
@ -125,15 +126,15 @@ id select_type table type possible_keys key key_len ref rows Extra
select count(*) from t1, t2 where t1.p = t2.i;
count(*)
3
cache index t2 keys in keycache1;
cache index t2 in keycache1;
Table Op Msg_type Msg_text
test.t2 assign_to_keycache status OK
update t2 set p=p+1000, i=2 where a='qqqq';
cache index t2 keys in keycache2;
cache index t2 in keycache2;
Table Op Msg_type Msg_text
test.t2 assign_to_keycache status OK
insert into t2 values (2000, 3, 'yyyy');
cache index t2 keys in keycache1;
cache index t2 in keycache1;
Table Op Msg_type Msg_text
test.t2 assign_to_keycache status OK
update t2 set p=3000 where a='zzzz';
@ -174,6 +175,12 @@ qqqq
yyyy
yyyy
zzzz
cache index t1 in unknown_key_cache;
ERROR HY000: Unknown key cache 'unknown_key_cache'
cache index t1 keys (unknown_key) in keycache1;
Table Op Msg_type Msg_text
test.t1 assign_to_keycache error Key column 'unknown_key' doesn't exist in table
test.t1 assign_to_keycache status Operation failed
select @@keycache2.key_buffer_size;
@@keycache2.key_buffer_size
4194304
@ -186,7 +193,11 @@ select @@keycache2.key_buffer_size;
0
select @@keycache2.key_cache_block_size;
@@keycache2.key_cache_block_size
0
1024
set global keycache2.key_buffer_size=1024*1024;
select @@keycache2.key_buffer_size;
@@keycache2.key_buffer_size
1048576
update t2 set p=4000 where a='zzzz';
update t1 set p=p+1;
set global keycache1.key_buffer_size=0;
@ -232,3 +243,17 @@ select p from t1;
p
3
12
create table t3 (like t1);
cache index t3 in small;
Table Op Msg_type Msg_text
test.t3 assign_to_keycache status OK
insert into t3 select * from t1;
cache index t3 in keycache2;
Table Op Msg_type Msg_text
test.t3 assign_to_keycache status OK
cache index t1,t2 in default;
Table Op Msg_type Msg_text
test.t1 assign_to_keycache status OK
test.t2 assign_to_keycache status OK
drop table t1,t2,t3;
set global keycache1.key_buffer_size=0;

View file

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

View file

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

View file

@ -77,13 +77,13 @@ show create table t1;
Table Create Table
t1 CREATE TEMPORARY TABLE `t1` (
`a` int(11) NOT NULL default '0'
) TYPE=MyISAM CHARSET=latin1
) TYPE=MyISAM DEFAULT CHARSET=latin1
alter table t1 rename t2;
show create table t2;
Table Create Table
t2 CREATE TEMPORARY TABLE `t2` (
`a` int(11) NOT NULL default '0'
) TYPE=MyISAM CHARSET=latin1
) TYPE=MyISAM DEFAULT CHARSET=latin1
drop table t2;
create table t1 (
test_set set( 'val1', 'val2', 'val3' ) not null default '',
@ -96,7 +96,7 @@ t1 CREATE TABLE `t1` (
`test_set` set('val1','val2','val3') NOT NULL default '',
`name` char(20) default 'O''Brien' COMMENT 'O''Brien as default',
`c` int(11) NOT NULL default '0' COMMENT 'int column'
) TYPE=MyISAM CHARSET=latin1 COMMENT='it''s a table'
) TYPE=MyISAM DEFAULT CHARSET=latin1 COMMENT='it''s a table'
show full columns from t1;
Field Type Collation Null Key Default Extra Privileges Comment
test_set set('val1','val2','val3') latin1_swedish_ci select,insert,update,references
@ -109,7 +109,7 @@ Table Create Table
t1 CREATE TABLE `t1` (
`a` int(11) NOT NULL default '0',
UNIQUE KEY `aa` (`a`)
) TYPE=MyISAM CHARSET=latin1
) TYPE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
create table t1 (a int not null, primary key (a));
show create table t1;
@ -117,7 +117,7 @@ Table Create Table
t1 CREATE TABLE `t1` (
`a` int(11) NOT NULL default '0',
PRIMARY KEY (`a`)
) TYPE=MyISAM CHARSET=latin1
) TYPE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
flush tables;
show open tables;
@ -135,7 +135,7 @@ t1 CREATE TABLE `t1` (
`a` int(11) NOT NULL default '0',
`b` char(10) default NULL,
KEY `b` (`b`)
) TYPE=MyISAM CHARSET=latin1 MIN_ROWS=10 MAX_ROWS=100 AVG_ROW_LENGTH=10 PACK_KEYS=1 CHECKSUM=1 DELAY_KEY_WRITE=1 ROW_FORMAT=FIXED COMMENT='test'
) TYPE=MyISAM DEFAULT CHARSET=latin1 MIN_ROWS=10 MAX_ROWS=100 AVG_ROW_LENGTH=10 PACK_KEYS=1 CHECKSUM=1 DELAY_KEY_WRITE=1 ROW_FORMAT=FIXED COMMENT='test'
alter table t1 MAX_ROWS=200 ROW_FORMAT=dynamic PACK_KEYS=0;
show create table t1;
Table Create Table
@ -143,7 +143,7 @@ t1 CREATE TABLE `t1` (
`a` int(11) NOT NULL default '0',
`b` varchar(10) default NULL,
KEY `b` (`b`)
) TYPE=MyISAM CHARSET=latin1 MIN_ROWS=10 MAX_ROWS=200 AVG_ROW_LENGTH=10 PACK_KEYS=0 CHECKSUM=1 DELAY_KEY_WRITE=1 ROW_FORMAT=DYNAMIC COMMENT='test'
) TYPE=MyISAM DEFAULT CHARSET=latin1 MIN_ROWS=10 MAX_ROWS=200 AVG_ROW_LENGTH=10 PACK_KEYS=0 CHECKSUM=1 DELAY_KEY_WRITE=1 ROW_FORMAT=DYNAMIC COMMENT='test'
ALTER TABLE t1 AVG_ROW_LENGTH=0 CHECKSUM=0 COMMENT="" MIN_ROWS=0 MAX_ROWS=0 PACK_KEYS=DEFAULT DELAY_KEY_WRITE=0 ROW_FORMAT=default;
show create table t1;
Table Create Table
@ -151,7 +151,7 @@ t1 CREATE TABLE `t1` (
`a` int(11) NOT NULL default '0',
`b` varchar(10) default NULL,
KEY `b` (`b`)
) TYPE=MyISAM CHARSET=latin1
) TYPE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
create table t1 (a decimal(9,2), b decimal (9,0), e double(9,2), f double(5,0), h float(3,2), i float(3,0));
show columns from t1;
@ -221,7 +221,7 @@ t1 CREATE TABLE `t1` (
`type_long_blob` longblob,
PRIMARY KEY (`type_tiny`),
KEY `type_short` (`type_short`)
) TYPE=MyISAM CHARSET=latin1 MIN_ROWS=10 MAX_ROWS=100 AVG_ROW_LENGTH=10 PACK_KEYS=1 CHECKSUM=1 DELAY_KEY_WRITE=1 ROW_FORMAT=FIXED COMMENT='test'
) TYPE=MyISAM DEFAULT CHARSET=latin1 MIN_ROWS=10 MAX_ROWS=100 AVG_ROW_LENGTH=10 PACK_KEYS=1 CHECKSUM=1 DELAY_KEY_WRITE=1 ROW_FORMAT=FIXED COMMENT='test'
insert into t1 (type_timestamp) values ("2003-02-07 10:00:01");
select * from t1;
type_bool type_tiny type_short type_mediumint type_bigint type_decimal type_numeric empty_char type_char type_varchar type_timestamp type_date type_time type_datetime type_year type_enum type_set type_tinyblob type_blob type_medium_blob type_long_blob

View file

@ -18,7 +18,7 @@ t1 CREATE TABLE `t1` (
`email` varchar(60) character set latin2 NOT NULL default '',
PRIMARY KEY (`a`),
UNIQUE KEY `email` TYPE BTREE (`email`)
) TYPE=HEAP CHARSET=latin1 ROW_FORMAT=DYNAMIC
) TYPE=HEAP DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC
set @@sql_mode="ansi_quotes";
show variables like 'sql_mode';
Variable_name Value
@ -31,7 +31,7 @@ t1 CREATE TABLE "t1" (
"email" varchar(60) character set latin2 NOT NULL default '',
PRIMARY KEY ("a"),
UNIQUE KEY "email" TYPE BTREE ("email")
) TYPE=HEAP CHARSET=latin1 ROW_FORMAT=DYNAMIC
) TYPE=HEAP DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC
set @@sql_mode="no_table_options";
show variables like 'sql_mode';
Variable_name Value
@ -57,7 +57,7 @@ t1 CREATE TABLE `t1` (
`email` varchar(60) character set latin2 NOT NULL default '',
PRIMARY KEY (`a`),
UNIQUE KEY `email` (`email`)
) TYPE=HEAP CHARSET=latin1 ROW_FORMAT=DYNAMIC
) TYPE=HEAP DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC
set @@sql_mode="no_field_options,mysql323,mysql40";
show variables like 'sql_mode';
Variable_name Value

View file

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

View file

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

View file

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

View file

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

View file

@ -4,14 +4,14 @@ show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` set('','a','b') NOT NULL default ''
) TYPE=MyISAM CHARSET=latin1
) TYPE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
create table t1 (a set (' ','a','b ') not null default 'b ');
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` set('','a','b') NOT NULL default 'b'
) TYPE=MyISAM CHARSET=latin1
) TYPE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
CREATE TABLE t1 ( user varchar(64) NOT NULL default '', path varchar(255) NOT NULL default '', privilege set('select','RESERVED30','RESERVED29','RESERVED28','RESERVED27','RESERVED26', 'RESERVED25','RESERVED24','data.delete','RESERVED22','RESERVED21', 'RESERVED20','data.insert.none','data.insert.approve', 'data.insert.delete','data.insert.move','data.insert.propose', 'data.insert.reject','RESERVED13','RESERVED12','RESERVED11','RESERVED10', 'RESERVED09','data.update','RESERVED07','RESERVED06','RESERVED05', 'RESERVED04','metadata.delete','metadata.put','RESERVED01','RESERVED00') NOT NULL default '', KEY user (user) ) TYPE=MyISAM CHARSET=utf8;
DROP TABLE t1;

View file

@ -486,7 +486,7 @@ a b
2 2
3 3
4 4
explain (select * from t1 where a=1 and b=10) union (select t1.a,t2.a from t1,t2 where t1.a=t2.a);
explain (select * from t1 where a=1 and b=10) union (select straight_join t1.a,t2.a from t1,t2 where t1.a=t2.a);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
2 UNION t1 index PRIMARY PRIMARY 4 NULL 4 Using index

View file

@ -170,6 +170,17 @@ select a,hex(a) from t1;
alter table t1 change a a char(10) character set koi8r;
select a,hex(a) from t1;
#
# Test ALTER TABLE .. CHARACTER SET ..
#
show create table t1;
alter table t1 DEFAULT CHARACTER SET latin1;
show create table t1;
alter table t1 CHARACTER SET latin1;
show create table t1;
alter table t1 DEFAULT CHARACTER SET cp1251;
show create table t1;
drop table t1;
#

View file

@ -16,7 +16,7 @@ ALTER TABLE t1 CHANGE comment comment CHAR(32) CHARACTER SET latin2 NOT NULL;
SHOW CREATE TABLE t1;
ALTER TABLE t1 ADD latin5_f CHAR(32) NOT NULL;
SHOW CREATE TABLE t1;
ALTER TABLE t1 CHARSET=latin2;
ALTER TABLE t1 DEFAULT CHARSET=latin2;
ALTER TABLE t1 ADD latin2_f CHAR(32) NOT NULL;
SHOW CREATE TABLE t1;
ALTER TABLE t1 DROP latin2_f, DROP latin5_f;

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 t2 values (1, 100), (1, 101), (1, 102), (2, 100), (2, 103), (2, 104), (3, 101), (3, 102), (3, 105);
SELECT d.pla_id, m2.mat_id FROM t1 m2 INNER JOIN (SELECT mp.pla_id, MIN(m1.matintnum) AS matintnum FROM t2 mp INNER JOIN t1 m1 ON mp.mat_id=m1.mat_id GROUP BY mp.pla_id) d ON d.matintnum=m2.matintnum;
SELECT d.pla_id, m2.test FROM t1 m2 INNER JOIN (SELECT mp.pla_id, MIN(m1.matintnum) AS matintnum FROM t2 mp INNER JOIN t1 m1 ON mp.mat_id=m1.mat_id GROUP BY mp.pla_id) d ON d.matintnum=m2.matintnum;
SELECT STRAIGHT_JOIN d.pla_id, m2.mat_id FROM t1 m2 INNER JOIN (SELECT mp.pla_id, MIN(m1.matintnum) AS matintnum FROM t2 mp INNER JOIN t1 m1 ON mp.mat_id=m1.mat_id GROUP BY mp.pla_id) d ON d.matintnum=m2.matintnum;
SELECT STRAIGHT_JOIN d.pla_id, m2.test FROM t1 m2 INNER JOIN (SELECT mp.pla_id, MIN(m1.matintnum) AS matintnum FROM t2 mp INNER JOIN t1 m1 ON mp.mat_id=m1.mat_id GROUP BY mp.pla_id) d ON d.matintnum=m2.matintnum;
explain SELECT d.pla_id, m2.mat_id FROM t1 m2 INNER JOIN (SELECT mp.pla_id, MIN(m1.matintnum) AS matintnum FROM t2 mp INNER JOIN t1 m1 ON mp.mat_id=m1.mat_id GROUP BY mp.pla_id) d ON d.matintnum=m2.matintnum;
explain SELECT d.pla_id, m2.test FROM t1 m2 INNER JOIN (SELECT mp.pla_id, MIN(m1.matintnum) AS matintnum FROM t2 mp INNER JOIN t1 m1 ON mp.mat_id=m1.mat_id GROUP BY mp.pla_id) d ON d.matintnum=m2.matintnum;
explain SELECT STRAIGHT_JOIN d.pla_id, m2.mat_id FROM t1 m2 INNER JOIN (SELECT mp.pla_id, MIN(m1.matintnum) AS matintnum FROM t2 mp INNER JOIN t1 m1 ON mp.mat_id=m1.mat_id GROUP BY mp.pla_id) d ON d.matintnum=m2.matintnum;
explain SELECT STRAIGHT_JOIN d.pla_id, m2.test FROM t1 m2 INNER JOIN (SELECT mp.pla_id, MIN(m1.matintnum) AS matintnum FROM t2 mp INNER JOIN t1 m1 ON mp.mat_id=m1.mat_id GROUP BY mp.pla_id) d ON d.matintnum=m2.matintnum;
drop table t1,t2;
#

View file

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

View file

@ -112,7 +112,7 @@ drop table t1, t2;
create table t1 (a int primary key);
insert into t1 values(1),(2);
select t1.a from t1 as t1 left join t1 as t2 using (a) left join t1 as t3 using (a) left join t1 as t4 using (a) left join t1 as t5 using (a) left join t1 as t6 using (a) left join t1 as t7 using (a) left join t1 as t8 using (a) left join t1 as t9 using (a) left join t1 as t10 using (a) left join t1 as t11 using (a) left join t1 as t12 using (a) left join t1 as t13 using (a) left join t1 as t14 using (a) left join t1 as t15 using (a) left join t1 as t16 using (a) left join t1 as t17 using (a) left join t1 as t18 using (a) left join t1 as t19 using (a) left join t1 as t20 using (a) left join t1 as t21 using (a) left join t1 as t22 using (a) left join t1 as t23 using (a) left join t1 as t24 using (a) left join t1 as t25 using (a) left join t1 as t26 using (a) left join t1 as t27 using (a) left join t1 as t28 using (a) left join t1 as t29 using (a) left join t1 as t30 using (a) left join t1 as t31 using (a);
--replace_result "31 tables" "XX tables" "62 tables" "XX tables"
--replace_result "31 tables" "XX tables" "61 tables" "XX tables"
--error 1116
select t1.a from t1 as t1 left join t1 as t2 using (a) left join t1 as t3 using (a) left join t1 as t4 using (a) left join t1 as t5 using (a) left join t1 as t6 using (a) left join t1 as t7 using (a) left join t1 as t8 using (a) left join t1 as t9 using (a) left join t1 as t10 using (a) left join t1 as t11 using (a) left join t1 as t12 using (a) left join t1 as t13 using (a) left join t1 as t14 using (a) left join t1 as t15 using (a) left join t1 as t16 using (a) left join t1 as t17 using (a) left join t1 as t18 using (a) left join t1 as t19 using (a) left join t1 as t20 using (a) left join t1 as t21 using (a) left join t1 as t22 using (a) left join t1 as t23 using (a) left join t1 as t24 using (a) left join t1 as t25 using (a) left join t1 as t26 using (a) left join t1 as t27 using (a) left join t1 as t28 using (a) left join t1 as t29 using (a) left join t1 as t30 using (a) left join t1 as t31 using (a) left join t1 as t32 using (a) left join t1 as t33 using (a) left join t1 as t34 using (a) left join t1 as t35 using (a) left join t1 as t36 using (a) left join t1 as t37 using (a) left join t1 as t38 using (a) left join t1 as t39 using (a) left join t1 as t40 using (a) left join t1 as t41 using (a) left join t1 as t42 using (a) left join t1 as t43 using (a) left join t1 as t44 using (a) left join t1 as t45 using (a) left join t1 as t46 using (a) left join t1 as t47 using (a) left join t1 as t48 using (a) left join t1 as t49 using (a) left join t1 as t50 using (a) left join t1 as t51 using (a) left join t1 as t52 using (a) left join t1 as t53 using (a) left join t1 as t54 using (a) left join t1 as t55 using (a) left join t1 as t56 using (a) left join t1 as t57 using (a) left join t1 as t58 using (a) left join t1 as t59 using (a) left join t1 as t60 using (a) left join t1 as t61 using (a) left join t1 as t62 using (a) left join t1 as t63 using (a) left join t1 as t64 using (a) left join t1 as t65 using (a);
drop table t1;

View file

@ -1,6 +1,9 @@
#
# Test of multiple key caches
#
--disable_warnings
drop table if exists t1, t2, t3;
--enable_warnings
SET @save_key_buffer=@@key_buffer_size;
@ -58,12 +61,9 @@ select @@keycache1.key_cache_block_size;
select @@key_buffer_size;
select @@key_cache_block_size;
set global keycache1.key_buffer_size=1024*1024;
--disable_warnings
drop table if exists t1, t2;
--enable_warnings
create table t1 (p int primary key, a char(10));
create table t1 (p int primary key, a char(10)) delay_key_write=1;
create table t2 (p int primary key, i int, a char(10), key k1(i), key k2(a));
insert into t1 values (1, 'qqqq'), (11, 'yyyy');
@ -75,7 +75,7 @@ select * from t2;
update t1 set p=2 where p=1;
update t2 set i=2 where i=1;
cache index t1 keys in keycache1;
cache index t1 keys (`primary`) in keycache1;
explain select p from t1;
select p from t1;
@ -84,11 +84,11 @@ select i from t2;
explain select count(*) from t1, t2 where t1.p = t2.i;
select count(*) from t1, t2 where t1.p = t2.i;
cache index t2 keys in keycache1;
cache index t2 in keycache1;
update t2 set p=p+1000, i=2 where a='qqqq';
cache index t2 keys in keycache2;
cache index t2 in keycache2;
insert into t2 values (2000, 3, 'yyyy');
cache index t2 keys in keycache1;
cache index t2 in keycache1;
update t2 set p=3000 where a='zzzz';
select * from t2;
explain select p from t2;
@ -98,12 +98,18 @@ select i from t2;
explain select a from t2;
select a from t2;
# Test some error conditions
--error 1287
cache index t1 in unknown_key_cache;
cache index t1 keys (unknown_key) in keycache1;
select @@keycache2.key_buffer_size;
select @@keycache2.key_cache_block_size;
set global keycache2.key_buffer_size=0;
select @@keycache2.key_buffer_size;
select @@keycache2.key_cache_block_size;
set global keycache2.key_buffer_size=1024*1024;
select @@keycache2.key_buffer_size;
update t2 set p=4000 where a='zzzz';
update t1 set p=p+1;
@ -119,4 +125,14 @@ select a from t2;
select * from t1;
select p from t1;
# Use the 'small' key cache
create table t3 (like t1);
cache index t3 in small;
insert into t3 select * from t1;
cache index t3 in keycache2;
cache index t1,t2 in default;
drop table t1,t2,t3;
# Cleanup
# We don't reset keycache2 as we want to ensure that mysqld will reset it
set global keycache1.key_buffer_size=0;

View file

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

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

View file

@ -29,7 +29,7 @@ libmysys_a_SOURCES = my_init.c my_getwd.c mf_getdate.c\
mf_path.c mf_loadpath.c\
my_open.c my_create.c my_dup.c my_seek.c my_read.c \
my_pread.c my_write.c \
mf_keycache.c my_crc32.c \
mf_keycache.c mf_keycaches.c my_crc32.c \
mf_iocache.c mf_iocache2.c mf_cache.c mf_tempfile.c \
mf_tempdir.c my_lock.c mf_brkhant.c my_alarm.c \
my_malloc.c my_realloc.c my_once.c mulalloc.c \

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))
{
hash->free=0; /* Allow call to hash_free */
DBUG_RETURN(TRUE);
DBUG_RETURN(1);
}
hash->key_offset=key_offset;
hash->key_length=key_length;

View file

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

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

View file

@ -682,60 +682,77 @@ ulonglong getopt_ull_limit_value(ulonglong num, const struct my_option *optp)
return num;
}
/*
function: init_variables
/*
Init one value to it's default values
SYNOPSIS
init_one_value()
option Option to initialize
value Pointer to variable
*/
static void init_one_value(const struct my_option *option, gptr *variable,
longlong value)
{
switch ((option->var_type & GET_TYPE_MASK)) {
case GET_BOOL:
*((my_bool*) variable)= (my_bool) value;
break;
case GET_INT:
*((int*) variable)= (int) value;
break;
case GET_UINT:
*((uint*) variable)= (uint) value;
break;
case GET_LONG:
*((long*) variable)= (long) value;
break;
case GET_ULONG:
*((ulong*) variable)= (ulong) value;
break;
case GET_LL:
*((longlong*) variable)= (longlong) value;
break;
case GET_ULL:
*((ulonglong*) variable)= (ulonglong) value;
break;
default: /* dummy default to avoid compiler warnings */
break;
}
}
/*
initialize all variables to their default values
SYNOPSIS
init_variables()
options Array of options
NOTES
We will initialize the value that is pointed to by options->value.
If the value is of type GET_ASK_ADDR, we will also ask for the address
for a value and initialize.
*/
static void init_variables(const struct my_option *options)
{
for (; options->name; options++)
{
gptr *value= (options->var_type & GET_ASK_ADDR ?
(*getopt_get_addr)("", 0, options) : options->value);
if (value)
{
switch ((options->var_type & GET_TYPE_MASK)) {
case GET_BOOL:
if (options->u_max_value)
*((my_bool*) options->u_max_value)= (my_bool) options->max_value;
*((my_bool*) value)= (my_bool) options->def_value;
break;
case GET_INT:
if (options->u_max_value)
*((int*) options->u_max_value)= (int) options->max_value;
*((int*) value)= (int) options->def_value;
break;
case GET_UINT:
if (options->u_max_value)
*((uint*) options->u_max_value)= (uint) options->max_value;
*((uint*) value)= (uint) options->def_value;
break;
case GET_LONG:
if (options->u_max_value)
*((long*) options->u_max_value)= (long) options->max_value;
*((long*) value)= (long) options->def_value;
break;
case GET_ULONG:
if (options->u_max_value)
*((ulong*) options->u_max_value)= (ulong) options->max_value;
*((ulong*) value)= (ulong) options->def_value;
break;
case GET_LL:
if (options->u_max_value)
*((longlong*) options->u_max_value)= (longlong) options->max_value;
*((longlong*) value)= (longlong) options->def_value;
break;
case GET_ULL:
if (options->u_max_value)
*((ulonglong*) options->u_max_value)= (ulonglong) options->max_value;
*((ulonglong*) value)= (ulonglong) options->def_value;
break;
default: /* dummy default to avoid compiler warnings */
break;
}
}
gptr *variable;
/*
We must set u_max_value first as for some variables
options->u_max_value == options->value and in this case we want to
set the value to default value.
*/
if (options->u_max_value)
init_one_value(options, options->u_max_value, options->max_value);
if (options->value)
init_one_value(options, options->value, options->def_value);
if (options->var_type & GET_ASK_ADDR &&
(variable= (*getopt_get_addr)("", 0, options)))
init_one_value(options, variable, options->def_value);
}
}

View file

@ -28,7 +28,7 @@ pthread_key(struct st_my_thread_var*, THR_KEY_mysys);
#else
pthread_key(struct st_my_thread_var, THR_KEY_mysys);
#endif /* USE_TLS */
pthread_mutex_t THR_LOCK_malloc,THR_LOCK_open,THR_LOCK_keycache,
pthread_mutex_t THR_LOCK_malloc,THR_LOCK_open,
THR_LOCK_lock,THR_LOCK_isam,THR_LOCK_myisam,THR_LOCK_heap,
THR_LOCK_net, THR_LOCK_charset;
#if !defined(HAVE_LOCALTIME_R) || !defined(HAVE_GMTIME_R)
@ -63,7 +63,6 @@ my_bool my_thread_global_init(void)
pthread_mutex_init(&THR_LOCK_malloc,MY_MUTEX_INIT_FAST);
pthread_mutex_init(&THR_LOCK_open,MY_MUTEX_INIT_FAST);
pthread_mutex_init(&THR_LOCK_keycache,MY_MUTEX_INIT_FAST);
pthread_mutex_init(&THR_LOCK_lock,MY_MUTEX_INIT_FAST);
pthread_mutex_init(&THR_LOCK_isam,MY_MUTEX_INIT_SLOW);
pthread_mutex_init(&THR_LOCK_myisam,MY_MUTEX_INIT_SLOW);
@ -96,7 +95,6 @@ void my_thread_global_end(void)
#endif
pthread_mutex_destroy(&THR_LOCK_malloc);
pthread_mutex_destroy(&THR_LOCK_open);
pthread_mutex_destroy(&THR_LOCK_keycache);
pthread_mutex_destroy(&THR_LOCK_lock);
pthread_mutex_destroy(&THR_LOCK_isam);
pthread_mutex_destroy(&THR_LOCK_myisam);

View file

@ -20,15 +20,28 @@
#include <m_string.h>
#include <m_ctype.h>
/***************************************************************************
** Search after a fieldtype. Endspace in x is not compared.
** If part, uniq field is found and full_name == 0 then x is expanded
** to full field.
** full_name has the following bit values:
** If & 1 accept only whole names
** If & 2 don't expand if half field
** If & 4 allow #number# as type
****************************************************************************/
/*
Search after a string in a list of strings. Endspace in x is not compared.
SYNOPSIS
find_type()
x String to find
lib TYPELIB (struct of pointer to values + count)
full_name bitmap of what to do
If & 1 accept only whole names
If & 2 don't expand if half field
If & 4 allow #number# as type
NOTES
If part, uniq field is found and full_name == 0 then x is expanded
to full field.
RETURN
-1 Too many matching values
0 No matching value
>0 Offset+1 in typelib for matched string
*/
int find_type(my_string x, TYPELIB *typelib, uint full_name)
{

View file

@ -754,7 +754,15 @@ mysql_free_result(MYSQL_RES *result)
if ((pkt_len=net_safe_read(result->handle)) == packet_error)
break;
if (pkt_len <= 8 && result->handle->net.read_pos[0] == 254)
{
if (protocol_41(result->handle))
{
char *pos= (char*) result->handle->net.read_pos;
result->handle->warning_count=uint2korr(pos); pos+=2;
result->handle->server_status=uint2korr(pos); pos+=2;
}
break; /* End of data */
}
}
result->handle->status=MYSQL_STATUS_READY;
}
@ -987,7 +995,7 @@ void mysql_read_default_options(struct st_mysql_options *options,
options->client_flag|= CLIENT_MULTI_RESULTS;
break;
case 31:
options->client_flag|= CLIENT_MULTI_QUERIES | CLIENT_MULTI_RESULTS;
options->client_flag|= CLIENT_MULTI_STATEMENTS | CLIENT_MULTI_RESULTS;
break;
default:
DBUG_PRINT("warning",("unknown option: %s",option[0]));
@ -1231,6 +1239,7 @@ MYSQL_DATA * STDCALL cli_read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields,
if (pkt_len > 1) /* MySQL 4.1 protocol */
{
mysql->warning_count= uint2korr(cp+1);
mysql->server_status= uint2korr(cp+3);
DBUG_PRINT("info",("warning_count: %ld", mysql->warning_count));
}
DBUG_PRINT("exit",("Got %d rows",result->rows));
@ -1256,7 +1265,10 @@ read_one_row(MYSQL *mysql,uint fields,MYSQL_ROW row, ulong *lengths)
if (pkt_len <= 8 && net->read_pos[0] == 254)
{
if (pkt_len > 1) /* MySQL 4.1 protocol */
{
mysql->warning_count= uint2korr(net->read_pos+1);
mysql->server_status= uint2korr(net->read_pos+3);
}
return 1; /* End of data */
}
prev_pos= 0; /* allowed to write at packet[-1] */
@ -1818,7 +1830,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
client_flag|=mysql->options.client_flag;
client_flag|=CLIENT_CAPABILITIES;
if (client_flag & CLIENT_MULTI_QUERIES)
if (client_flag & CLIENT_MULTI_STATEMENTS)
client_flag|= CLIENT_MULTI_RESULTS;
#ifdef HAVE_OPENSSL

View file

@ -226,15 +226,10 @@ err:
int ha_myisam::open(const char *name, int mode, uint test_if_locked)
{
KEY_CACHE_VAR *key_cache;
if (!(file=mi_open(name, mode, test_if_locked)))
return (my_errno ? my_errno : -1);
/* Synchronize key cache assignment of the handler */
KEY_CACHE_VAR *key_cache= table->key_cache ? table->key_cache :
&dflt_key_cache_var;
VOID(mi_extra(file, HA_EXTRA_SET_KEY_CACHE,
(void*) &key_cache->cache));
if (test_if_locked & (HA_OPEN_IGNORE_IF_LOCKED | HA_OPEN_TMP_TABLE))
VOID(mi_extra(file, HA_EXTRA_NO_WAIT_LOCK, 0));
info(HA_STATUS_NO_LOCK | HA_STATUS_VARIABLE | HA_STATUS_CONST);
@ -698,93 +693,48 @@ int ha_myisam::repair(THD *thd, MI_CHECK &param, bool optimize)
/*
Assign table indexes to a key cache.
Assign table indexes to a specific key cache.
*/
int ha_myisam::assign_to_keycache(THD* thd, HA_CHECK_OPT *check_opt)
{
uint len;
KEY_CACHE_VAR *old_key_cache;
KEY_CACHE_VAR *new_key_cache;
const char *errmsg=0;
KEY_CACHE_VAR *new_key_cache= check_opt->key_cache;
const char *errmsg= 0;
int error= HA_ADMIN_OK;
ulonglong map= ~(ulonglong) 0;
TABLE_LIST *table_list= table->pos_in_table_list;
const char *new_key_cache_name= table_list->option ?
(const char *) table_list->option :
DEFAULT_KEY_CACHE_NAME;
KEY_CACHE_ASMT *key_cache_asmt= table->key_cache_asmt;
bool triggered= key_cache_asmt->triggered;
DBUG_ENTER("ha_myisam::assign_to_keycache");
VOID(pthread_mutex_lock(&LOCK_assign));
old_key_cache= key_cache_asmt->key_cache;
/* Check validity of the index references */
if (!triggered && table_list->use_index)
if (table_list->use_index)
{
/* We only come here when the user did specify an index map */
key_map kmap;
get_key_map_from_key_list(&kmap, table, table_list->use_index);
if (kmap.is_set_all())
if (get_key_map_from_key_list(&kmap, table, table_list->use_index))
{
errmsg= thd->net.last_error;
error= HA_ADMIN_FAILED;
goto err;
}
if (!kmap.is_clear_all())
map= kmap.to_ulonglong();
map= kmap.to_ulonglong();
}
len= strlen(new_key_cache_name);
new_key_cache= get_or_create_key_cache(new_key_cache_name, len);
if (old_key_cache == new_key_cache)
{
/* Nothing to do: table is assigned to the same key cache */
goto ok;
}
if (!new_key_cache ||
(!new_key_cache->cache && ha_key_cache(new_key_cache)))
{
if (key_cache_asmt->triggered)
error= HA_ERR_OUT_OF_MEM;
else
{
char buf[ERRMSGSIZE];
my_snprintf(buf, ERRMSGSIZE,
"Failed to create key cache %s", new_key_cache_name);
errmsg= buf;
error= HA_ADMIN_FAILED;
}
goto err;
}
reassign_key_cache(key_cache_asmt, new_key_cache);
VOID(pthread_mutex_unlock(&LOCK_assign));
error= mi_assign_to_keycache(file, map, new_key_cache, &LOCK_assign);
VOID(pthread_mutex_lock(&LOCK_assign));
if (error && !key_cache_asmt->triggered)
if ((error= mi_assign_to_key_cache(file, map, new_key_cache)))
{
switch (error) {
default:
char buf[ERRMSGSIZE+20];
my_snprintf(buf, ERRMSGSIZE,
"Failed to flush to index file (errno: %d)", my_errno);
char buf[80];
my_snprintf(buf, sizeof(buf),
"Failed to flush to index file (errno: %d)", error);
errmsg= buf;
}
error= HA_ADMIN_CORRUPT;
goto err;
}
goto ok;
err:
if (!triggered)
if (error != HA_ADMIN_OK)
{
/* Send error to user */
MI_CHECK param;
myisamchk_init(&param);
param.thd= thd;
@ -793,32 +743,7 @@ int ha_myisam::assign_to_keycache(THD* thd, HA_CHECK_OPT *check_opt)
param.table_name= table->table_name;
param.testflag= 0;
mi_check_print_error(&param, errmsg);
}
ok:
if (--key_cache_asmt->requests)
{
/* There is a queue of assignments for the table */
/* Remove the first member from the queue */
struct st_my_thread_var *last= key_cache_asmt->queue;
struct st_my_thread_var *thread= last->next;
if (thread->next == thread)
key_cache_asmt->queue= 0;
else
{
last->next= thread->next;
last->next->prev= &last->next;
thread->next= 0;
}
/* Signal the first waiting thread to proceed */
VOID(pthread_cond_signal(&thread->suspend));
}
key_cache_asmt->triggered= 0;
VOID(pthread_mutex_unlock(&LOCK_assign));
DBUG_RETURN(error);
}

View file

@ -35,9 +35,12 @@
const char **ha_myisammrg::bas_ext() const
{ static const char *ext[]= { ".MRG", NullS }; return ext; }
int ha_myisammrg::open(const char *name, int mode, uint test_if_locked)
{
char name_buff[FN_REFLEN];
KEY_CACHE_VAR *key_cache;
DBUG_PRINT("info", ("ha_myisammrg::open"));
if (!(file=myrg_open(fn_format(name_buff,name,"","",2 | 4), mode,
test_if_locked)))
@ -45,12 +48,6 @@ int ha_myisammrg::open(const char *name, int mode, uint test_if_locked)
DBUG_PRINT("info", ("ha_myisammrg::open exit %d", my_errno));
return (my_errno ? my_errno : -1);
}
/* Synchronize key cache assignment for the file */
KEY_CACHE_VAR *key_cache= table->key_cache ? table->key_cache :
&dflt_key_cache_var;
VOID(myrg_extra(file, HA_EXTRA_SET_KEY_CACHE,
(void*) &key_cache->cache));
DBUG_PRINT("info", ("ha_myisammrg::open myrg_extrafunc..."))
myrg_extrafunc(file, query_cache_invalidate_by_MyISAM_filename_ref);
if (!(test_if_locked == HA_OPEN_WAIT_IF_LOCKED ||

View file

@ -1105,67 +1105,6 @@ int ha_create_table(const char *name, HA_CREATE_INFO *create_info,
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)
{
char buff[FN_REFLEN];
@ -1178,3 +1117,85 @@ void st_ha_check_opt::init()
flags= sql_flags= 0;
sort_buffer_size = current_thd->variables.myisam_sort_buff_size;
}
/*****************************************************************************
Key cache handling.
This code is only relevant for ISAM/MyISAM tables
key_cache->cache may be 0 only in the case where a key cache is not
initialized or when we where not able to init the key cache in a previous
call to ha_init_key_cache() (probably out of memory)
*****************************************************************************/
/* Init a key cache if it has not been initied before */
int ha_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_PACK_KEYS 128
#define HA_CREATE_USED_CHARSET 256
#define HA_CREATE_USED_DEFAULT_CHARSET 512
typedef struct st_thd_trans {
void *bdb_tid;
@ -157,7 +158,7 @@ enum enum_tx_isolation { ISO_READ_UNCOMMITTED, ISO_READ_COMMITTED,
typedef struct st_ha_create_information
{
CHARSET_INFO *table_charset;
CHARSET_INFO *table_charset, *default_table_charset;
char *comment,*password;
char *data_file_name, *index_file_name;
ulonglong max_rows,min_rows;
@ -180,15 +181,18 @@ typedef struct st_ha_create_information
struct st_table;
typedef struct st_table TABLE;
typedef struct st_key_cache_asmt KEY_CACHE_ASMT;
typedef struct st_ha_check_opt
{
ulong sort_buffer_size;
uint flags; /* isam layer flags (e.g. for myisamchk) */
uint sql_flags; /* sql layer flags - for something myisamchk cannot do */
KEY_CACHE_VAR *key_cache; /* new key cache when changing key cache */
void init();
} HA_CHECK_OPT;
class handler :public Sql_alloc
{
protected:
@ -390,7 +394,7 @@ int ha_create_table(const char *name, HA_CREATE_INFO *create_info,
bool update_create_info);
int ha_delete_table(enum db_type db_type, const char *path);
void ha_drop_database(char* path);
int ha_key_cache(KEY_CACHE_VAR *key_cache);
int ha_init_key_cache(const char *name, KEY_CACHE_VAR *key_cache);
int ha_resize_key_cache(KEY_CACHE_VAR *key_cache);
int ha_change_key_cache_param(KEY_CACHE_VAR *key_cache);
int ha_end_key_cache(KEY_CACHE_VAR *key_cache);
@ -407,3 +411,5 @@ int ha_autocommit_or_rollback(THD *thd, int error);
void ha_set_spin_retries(uint retries);
bool ha_flush_logs(void);
int ha_recovery_logging(THD *thd, bool on);
int ha_change_key_cache(KEY_CACHE_VAR *old_key_cache,
KEY_CACHE_VAR *new_key_cache);

View file

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

View file

@ -715,7 +715,14 @@ class Item_func_in :public Item_int_func
}
longlong val_int();
void fix_length_and_dec();
~Item_func_in() { delete array; delete in_item; }
~Item_func_in() {}
void cleanup()
{
delete array;
delete in_item;
array= 0;
in_item= 0;
}
optimize_type select_optimize() const
{ return array ? OPTIMIZE_KEY : OPTIMIZE_NONE; }
void print(String *str);

View file

@ -2648,6 +2648,8 @@ err:
void Item_func_match::init_search(bool no_order)
{
DBUG_ENTER("Item_func_match::init_search");
/* Check if init_search() has been called before */
if (ft_handler)
DBUG_VOID_RETURN;
@ -2685,7 +2687,8 @@ void Item_func_match::init_search(bool no_order)
ft_tmp= &search_value;
}
if (join_key && !no_order) flags|=FT_SORTED;
if (join_key && !no_order)
flags|=FT_SORTED;
ft_handler=table->file->ft_init_ext(flags, key,
(byte*) ft_tmp->ptr(),
ft_tmp->length());

View file

@ -427,8 +427,6 @@ bool check_stack_overrun(THD *thd,char *dummy);
void table_cache_init(void);
void table_cache_free(void);
uint cached_tables(void);
void assign_cache_init(void);
void assign_cache_free(void);
void reassign_key_cache(KEY_CACHE_ASMT *key_cache_asmt,
KEY_CACHE_VAR *new_key_cache);
void kill_mysql(void);
@ -460,10 +458,11 @@ int mysql_analyze_table(THD* thd, TABLE_LIST* table_list,
HA_CHECK_OPT* check_opt);
int mysql_optimize_table(THD* thd, TABLE_LIST* table_list,
HA_CHECK_OPT* check_opt);
int mysql_assign_to_keycache(THD* thd, TABLE_LIST* table_list);
int mysql_assign_to_keycache(THD* thd, TABLE_LIST* table_list,
LEX_STRING *key_cache_name);
int mysql_preload_keys(THD* thd, TABLE_LIST* table_list);
int reassign_keycache_tables(THD* thd, KEY_CACHE_VAR* src_cache,
char *dest_name, bool remove_fl);
int reassign_keycache_tables(THD* thd, KEY_CACHE_VAR *src_cache,
KEY_CACHE_VAR *dst_cache);
bool check_simple_select();
@ -662,7 +661,7 @@ enum find_item_error_report_type {REPORT_ALL_ERRORS, REPORT_EXCEPT_NOT_FOUND,
extern const Item **not_found_item;
Item ** find_item_in_list(Item *item, List<Item> &items, uint *counter,
find_item_error_report_type report_error);
void get_key_map_from_key_list(key_map *map, TABLE *table,
bool get_key_map_from_key_list(key_map *map, TABLE *table,
List<String> *index_list);
bool insert_fields(THD *thd,TABLE_LIST *tables,
const char *db_name, const char *table_name,
@ -849,7 +848,7 @@ extern pthread_mutex_t LOCK_mysql_create_db,LOCK_Acl,LOCK_open,
LOCK_error_log, LOCK_delayed_insert,
LOCK_delayed_status, LOCK_delayed_create, LOCK_crypt, LOCK_timezone,
LOCK_slave_list, LOCK_active_mi, LOCK_manager,
LOCK_global_system_variables, LOCK_user_conn, LOCK_assign;
LOCK_global_system_variables, LOCK_user_conn;
extern rw_lock_t LOCK_grant;
extern pthread_cond_t COND_refresh, COND_thread_count, COND_manager;
extern pthread_attr_t connection_attrib;
@ -866,6 +865,8 @@ extern SHOW_COMP_OPTION have_berkeley_db;
extern struct system_variables global_system_variables;
extern struct system_variables max_system_variables;
extern struct rand_struct sql_rand;
extern KEY_CACHE_VAR *sql_key_cache;
extern KEY_CACHE_HANDLE sql_key_cache_handle;
extern const char *opt_date_time_formats[];
extern KNOWN_DATE_TIME_FORMAT known_date_time_formats[];

View file

@ -355,6 +355,7 @@ struct system_variables max_system_variables;
MY_TMPDIR mysql_tmpdir_list;
MY_BITMAP temp_pool;
KEY_CACHE_VAR *sql_key_cache;
CHARSET_INFO *system_charset_info, *files_charset_info ;
CHARSET_INFO *national_charset_info, *table_alias_charset;
@ -373,7 +374,6 @@ pthread_mutex_t LOCK_mysql_create_db, LOCK_Acl, LOCK_open, LOCK_thread_count,
LOCK_delayed_insert, LOCK_delayed_status, LOCK_delayed_create,
LOCK_crypt, LOCK_bytes_sent, LOCK_bytes_received,
LOCK_global_system_variables,
LOCK_assign,
LOCK_user_conn, LOCK_slave_list, LOCK_active_mi;
rw_lock_t LOCK_grant;
pthread_cond_t COND_refresh,COND_thread_count, COND_slave_stopped,
@ -900,7 +900,6 @@ void clean_up(bool print_message)
#endif
query_cache_destroy();
table_cache_free();
assign_cache_free();
hostname_cache_free();
item_user_lock_free();
lex_free(); /* Free some memory */
@ -910,9 +909,8 @@ void clean_up(bool print_message)
udf_free();
#endif
(void) ha_panic(HA_PANIC_CLOSE); /* close all tables and logs */
process_key_caches(&ha_end_key_cache);
ha_end_key_cache(&dflt_key_cache_var);
delete_elements(&key_caches, free_key_cache);
delete_elements(&key_caches, (void (*)(const char*, gptr)) free_key_cache);
multi_keycache_free();
end_thr_alarm(1); /* Free allocated memory */
#ifdef USE_RAID
end_raid();
@ -997,7 +995,6 @@ static void clean_up_mutexes()
#endif
(void) pthread_mutex_destroy(&LOCK_active_mi);
(void) pthread_mutex_destroy(&LOCK_global_system_variables);
(void) pthread_mutex_destroy(&LOCK_assign);
(void) pthread_cond_destroy(&COND_thread_count);
(void) pthread_cond_destroy(&COND_refresh);
(void) pthread_cond_destroy(&COND_thread_cache);
@ -1568,14 +1565,14 @@ We will try our best to scrape up some info that will hopefully help diagnose\n\
the problem, but since we have already crashed, something is definitely wrong\n\
and this may fail.\n\n");
fprintf(stderr, "key_buffer_size=%lu\n",
(ulong) dflt_key_cache_var.buff_size);
(ulong) sql_key_cache->buff_size);
fprintf(stderr, "read_buffer_size=%ld\n", global_system_variables.read_buff_size);
fprintf(stderr, "max_used_connections=%ld\n", max_used_connections);
fprintf(stderr, "max_connections=%ld\n", max_connections);
fprintf(stderr, "threads_connected=%d\n", thread_count);
fprintf(stderr, "It is possible that mysqld could use up to \n\
key_buffer_size + (read_buffer_size + sort_buffer_size)*max_connections = %ld K\n\
bytes of memory\n", ((ulong) dflt_key_cache_var.buff_size +
bytes of memory\n", ((ulong) sql_key_cache->buff_size +
(global_system_variables.read_buff_size +
global_system_variables.sortbuff_size) *
max_connections)/ 1024);
@ -2204,7 +2201,6 @@ static int init_thread_environment()
(void) pthread_mutex_init(&LOCK_user_conn, MY_MUTEX_INIT_FAST);
(void) pthread_mutex_init(&LOCK_active_mi, MY_MUTEX_INIT_FAST);
(void) pthread_mutex_init(&LOCK_global_system_variables, MY_MUTEX_INIT_FAST);
(void) pthread_mutex_init(&LOCK_assign, MY_MUTEX_INIT_FAST);
(void) my_rwlock_init(&LOCK_grant, NULL);
(void) pthread_cond_init(&COND_thread_count,NULL);
(void) pthread_cond_init(&COND_refresh,NULL);
@ -2256,7 +2252,6 @@ static int init_server_components()
{
DBUG_ENTER("init_server_components");
table_cache_init();
assign_cache_init();
hostname_cache_init();
query_cache_result_size_limit(query_cache_limit);
query_cache_set_min_res_unit(query_cache_min_res_unit);
@ -2328,9 +2323,10 @@ Now disabling --log-slave-updates.");
if (opt_myisam_log)
(void) mi_log(1);
ha_key_cache(&dflt_key_cache_var);
process_key_caches(&ha_key_cache);
/* call ha_init_key_cache() on all key caches to init them */
process_key_caches(&ha_init_key_cache);
/* We must set dflt_key_cache in case we are using ISAM tables */
dflt_keycache= &sql_key_cache->cache;
#if defined(HAVE_MLOCKALL) && defined(MCL_CURRENT)
if (locked_in_memory && !geteuid())
@ -4321,25 +4317,28 @@ replicating a LOAD DATA INFILE command.",
{"key_buffer_size", OPT_KEY_BUFFER_SIZE,
"The size of the buffer used for index blocks for MyISAM tables. Increase this to get better index handling (for all reads and multiple writes) to as much as you can afford; 64M on a 256M machine that mainly runs MySQL is quite common.",
(gptr*) &dflt_key_cache_var.buff_size,
(gptr*) &dflt_key_cache_var.buff_size, 0,
(enum get_opt_var_type) (GET_ULL | GET_ASK_ADDR),
(gptr*) 0,
0, (enum get_opt_var_type) (GET_ULL | GET_ASK_ADDR),
REQUIRED_ARG, KEY_CACHE_SIZE, MALLOC_OVERHEAD, (long) ~0, MALLOC_OVERHEAD,
IO_SIZE, 0},
{"key_cache_block_size", OPT_KEY_CACHE_BLOCK_SIZE,
"The default size of key cache blocks",
(gptr*) &dflt_key_cache_var.block_size,
(gptr*) &dflt_key_cache_var.block_size, 0, GET_ULONG,
REQUIRED_ARG, KEY_CACHE_BLOCK_SIZE , 512, 1024*16, MALLOC_OVERHEAD, 512, 0},
(gptr*) 0,
0, (enum get_opt_var_type) (GET_ULONG | GET_ASK_ADDR), REQUIRED_ARG,
KEY_CACHE_BLOCK_SIZE , 512, 1024*16, MALLOC_OVERHEAD, 512, 0},
{"key_cache_division_limit", OPT_KEY_CACHE_DIVISION_LIMIT,
"The minimum percentage of warm blocks in key cache",
(gptr*) &dflt_key_cache_var.division_limit,
(gptr*) &dflt_key_cache_var.division_limit, 0, GET_ULONG,
REQUIRED_ARG, 100, 1, 100, 0, 1, 0},
(gptr*) 0,
0, (enum get_opt_var_type) (GET_ULONG | GET_ASK_ADDR) , REQUIRED_ARG, 100,
1, 100, 0, 1, 0},
{"key_cache_division_age_threshold", OPT_KEY_CACHE_AGE_THRESHOLD,
"This characterizes the number of hits a hot block has to be untouched until it is considered aged enough to be downgraded to a warm block. This specifies the percentage ratio of that number of hits to the total number of blocks in key cache",
(gptr*) &dflt_key_cache_var.age_threshold,
(gptr*) &dflt_key_cache_var.age_threshold, 0, GET_ULONG,
REQUIRED_ARG, 300, 100, ~0L, 0, 100, 0},
(gptr*) 0,
0, (enum get_opt_var_type) (GET_ULONG | GET_ASK_ADDR), REQUIRED_ARG,
300, 100, ~0L, 0, 100, 0},
{"long_query_time", OPT_LONG_QUERY_TIME,
"Log all queries that have taken more than long_query_time seconds to execute to file.",
(gptr*) &global_system_variables.long_query_time,
@ -4758,19 +4757,19 @@ struct show_var_st status_vars[]= {
{"Handler_rollback", (char*) &ha_rollback_count, SHOW_LONG},
{"Handler_update", (char*) &ha_update_count, SHOW_LONG},
{"Handler_write", (char*) &ha_write_count, SHOW_LONG},
{"Key_blocks_not_flushed", (char*) &dflt_key_cache_var.blocks_changed,
SHOW_KEY_CACHE_LONG},
{"Key_blocks_used", (char*) &dflt_key_cache_var.blocks_used,
SHOW_LONG_CONST},
SHOW_KEY_CACHE_LONG},
{"Key_read_requests", (char*) &dflt_key_cache_var.cache_r_requests,
SHOW_LONG},
SHOW_KEY_CACHE_LONG},
{"Key_reads", (char*) &dflt_key_cache_var.cache_read,
SHOW_LONG},
SHOW_KEY_CACHE_LONG},
{"Key_write_requests", (char*) &dflt_key_cache_var.cache_w_requests,
SHOW_LONG},
SHOW_KEY_CACHE_LONG},
{"Key_writes", (char*) &dflt_key_cache_var.cache_write,
SHOW_LONG},
SHOW_KEY_CACHE_LONG},
{"Max_used_connections", (char*) &max_used_connections, SHOW_LONG},
{"Not_flushed_key_blocks", (char*) &dflt_key_cache_var.blocks_changed,
SHOW_LONG_CONST},
{"Not_flushed_delayed_rows", (char*) &delayed_rows_in_use, SHOW_LONG_CONST},
{"Open_tables", (char*) 0, SHOW_OPENTABLES},
{"Open_files", (char*) &my_file_opened, SHOW_LONG_CONST},
@ -4984,8 +4983,9 @@ static void mysql_init_variables(void)
threads.empty();
thread_cache.empty();
key_caches.empty();
if (!get_or_create_key_cache(DEFAULT_KEY_CACHE_NAME,
strlen(DEFAULT_KEY_CACHE_NAME)))
multi_keycache_init();
if (!(sql_key_cache= get_or_create_key_cache(default_key_cache_base.str,
default_key_cache_base.length)))
exit(1);
/* Initialize structures that is used when processing options */
@ -5075,9 +5075,9 @@ static void mysql_init_variables(void)
have_crypt=SHOW_OPTION_NO;
#endif
#ifdef HAVE_COMPRESS
SHOW_COMP_OPTION have_compress= SHOW_OPTION_YES;
have_compress= SHOW_OPTION_YES;
#else
SHOW_COMP_OPTION have_compress= SHOW_OPTION_NO;
have_compress= SHOW_OPTION_NO;
#endif
#ifdef HAVE_LIBWRAP
libwrapName= NullS;
@ -5699,13 +5699,6 @@ static void get_options(int argc,char **argv)
init_global_datetime_format(TIMESTAMP_DATETIME,
&global_system_variables.datetime_format))
exit(1);
/* Set up default values for a key cache */
KEY_CACHE_VAR *key_cache= &dflt_key_cache_var;
dflt_key_cache_block_size= key_cache->block_size;
dflt_key_buff_size= key_cache->buff_size;
dflt_key_cache_division_limit= key_cache->division_limit;
dflt_key_cache_age_threshold= key_cache->age_threshold;
}

View file

@ -120,6 +120,10 @@ void send_error(THD *thd, uint sql_errno, const char *err)
#endif /* EMBEDDED_LIBRARY*/
thd->is_fatal_error=0; // Error message is given
thd->net.report_error= 0;
/* Abort multi-result sets */
thd->lex.found_colon= 0;
thd->server_status= ~SERVER_MORE_RESULTS_EXISTS;
DBUG_VOID_RETURN;
}
@ -338,7 +342,14 @@ send_eof(THD *thd, bool no_flush)
uint tmp= min(thd->total_warn_count, 65535);
buff[0]=254;
int2store(buff+1, tmp);
int2store(buff+3, 0); // No flags yet
/*
The following test should never be true, but it's better to do it
because if 'is_fatal_error' is set the server is not going to execute
other queries (see the if test in dispatch_command / COM_QUERY)
*/
if (thd->is_fatal_error)
thd->server_status= ~SERVER_MORE_RESULTS_EXISTS;
int2store(buff+3, thd->server_status);
VOID(my_net_write(net,(char*) buff,5));
VOID(net_flush(net));
}

View file

@ -60,11 +60,6 @@
#include "ha_innodb.h"
#endif
ulonglong dflt_key_buff_size;
uint dflt_key_cache_block_size;
uint dflt_key_cache_division_limit;
uint dflt_key_cache_age_threshold;
static HASH system_variable_hash;
const char *bool_type_names[]= { "OFF", "ON", NullS };
TYPELIB bool_typelib=
@ -148,11 +143,15 @@ sys_var_thd_ulong sys_interactive_timeout("interactive_timeout",
sys_var_thd_ulong sys_join_buffer_size("join_buffer_size",
&SV::join_buff_size);
sys_var_key_buffer_size sys_key_buffer_size("key_buffer_size");
sys_var_key_cache_block_size sys_key_cache_block_size("key_cache_block_size");
sys_var_key_cache_division_limit
sys_key_cache_division_limit("key_cache_division_limit");
sys_var_key_cache_age_threshold
sys_key_cache_age_threshold("key_cache_age_threshold");
sys_var_key_cache_long sys_key_cache_block_size("key_cache_block_size",
offsetof(KEY_CACHE_VAR,
block_size));
sys_var_key_cache_long sys_key_cache_division_limit("key_cache_division_limit",
offsetof(KEY_CACHE_VAR,
division_limit));
sys_var_key_cache_long sys_key_cache_age_threshold("key_cache_age_threshold",
offsetof(KEY_CACHE_VAR,
age_threshold));
sys_var_bool_ptr sys_local_infile("local_infile",
&opt_local_infile);
sys_var_thd_bool sys_log_warnings("log_warnings", &SV::log_warnings);
@ -1266,7 +1265,13 @@ Item *sys_var::item(THD *thd, enum_var_type var_type, LEX_STRING *base)
}
switch (type()) {
case SHOW_LONG:
return new Item_uint((int32) *(ulong*) value_ptr(thd, var_type, base));
{
ulong value;
pthread_mutex_lock(&LOCK_global_system_variables);
value= *(ulong*) value_ptr(thd, var_type, base);
pthread_mutex_unlock(&LOCK_global_system_variables);
return new Item_uint((int32) value);
}
case SHOW_LONGLONG:
{
longlong value;
@ -1771,24 +1776,21 @@ void sys_var_collation_server::set_default(THD *thd, enum_var_type type)
}
static LEX_STRING default_key_cache_base= {(char *) DEFAULT_KEY_CACHE_NAME, 7};
LEX_STRING default_key_cache_base= {(char *) "default", 7 };
static KEY_CACHE_VAR zero_key_cache=
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
static KEY_CACHE_VAR *get_key_cache(LEX_STRING *cache_name)
KEY_CACHE_VAR *get_key_cache(LEX_STRING *cache_name)
{
if (!cache_name || !cache_name->str || !cache_name->length ||
cache_name->str == default_key_cache_base.str ||
(cache_name->length == default_key_cache_base.length &&
!memcmp(cache_name->str, default_key_cache_base.str,
default_key_cache_base.length)))
safe_mutex_assert_owner(&LOCK_global_system_variables);
if (!cache_name || ! cache_name->length)
cache_name= &default_key_cache_base;
return ((KEY_CACHE_VAR*) find_named(&key_caches,
cache_name->str, cache_name->length,
0));
cache_name->str, cache_name->length, 0));
}
byte *sys_var_key_cache_param::value_ptr(THD *thd, enum_var_type type,
LEX_STRING *base)
{
@ -1798,115 +1800,134 @@ byte *sys_var_key_cache_param::value_ptr(THD *thd, enum_var_type type,
return (byte*) key_cache + offset ;
}
bool sys_var_key_buffer_size::update(THD *thd, set_var *var)
{
ulonglong tmp= var->save_result.ulonglong_value;
LEX_STRING *base_name= &var->base;
KEY_CACHE_VAR *key_cache;
bool error= 0;
/* If no basename, assume it's for the key cache named 'default' */
if (!base_name->length)
base_name= &default_key_cache_base;
KEY_CACHE_VAR *key_cache= get_key_cache(base_name);
pthread_mutex_lock(&LOCK_global_system_variables);
key_cache= get_key_cache(base_name);
if (!key_cache)
{
/* Key cache didn't exists */
if (!tmp) // Tried to delete cache
return 0; // Ok, nothing to do
if (!(key_cache= create_key_cache(base_name->str,
base_name->length)))
return 1;
goto end; // Ok, nothing to do
if (!(key_cache= create_key_cache(base_name->str, base_name->length)))
{
error= 1;
goto end;
}
}
/*
Abort if some other thread is changing the key cache
TODO: This should be changed so that we wait until the previous
assignment is done and then do the new assign
*/
if (key_cache->in_init)
goto end;
if (!tmp) // Zero size means delete
{
if (!key_cache->cache)
return 0;
/* Delete not default key caches */
if (key_cache != &dflt_key_cache_var)
if (key_cache == sql_key_cache)
goto end; // Ignore default key cache
if (key_cache->cache) // If initied
{
/*
Move tables using this key cache to the default key cache
and remove this key cache if no tables are assigned to it
Move tables using this key cache to the default key cache
and clear the old key cache.
*/
NAMED_LIST *list;
key_cache= (KEY_CACHE_VAR *) find_named(&key_caches, base_name->str,
base_name->length, &list);
delete list;
int rc= reassign_keycache_tables(thd, key_cache,
default_key_cache_base.str, 1);
my_free((char*) key_cache, MYF(0));
return rc;
key_cache->in_init= 1;
pthread_mutex_unlock(&LOCK_global_system_variables);
error= reassign_keycache_tables(thd, key_cache, sql_key_cache);
pthread_mutex_lock(&LOCK_global_system_variables);
key_cache->in_init= 0;
}
return 0;
/*
We don't delete the key cache as some running threads my still be
in the key cache code with a pointer to the deleted (empty) key cache
*/
goto end;
}
key_cache->buff_size= (ulonglong) getopt_ull_limit_value(tmp, option_limits);
/* If key cache didn't existed initialize it, else resize it */
key_cache->in_init= 1;
pthread_mutex_unlock(&LOCK_global_system_variables);
if (!key_cache->cache)
return (bool)(ha_key_cache(key_cache));
error= (bool) (ha_init_key_cache("", key_cache));
else
return (bool)(ha_resize_key_cache(key_cache));
error= (bool)(ha_resize_key_cache(key_cache));
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();
LEX_STRING *base_name= &var->base;
bool error= 0;
if (!base_name->length)
base_name= &default_key_cache_base;
pthread_mutex_lock(&LOCK_global_system_variables);
KEY_CACHE_VAR *key_cache= get_key_cache(base_name);
if (!key_cache && !(key_cache= create_key_cache(base_name->str,
base_name->length)))
return 1;
{
error= 1;
goto end;
}
key_cache->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)
/* 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*) (((char*) key_cache) + offset))=
(ulong) getopt_ull_limit_value(tmp, option_limits);
if (key_cache->cache)
/* Do not build a new key cache here */
return (bool) (ha_change_key_cache_param(key_cache));
return 0;
}
/*
Don't create a new key cache if it didn't exist
(key_caches are created only when the user sets block_size)
*/
key_cache->in_init= 1;
bool sys_var_key_cache_age_threshold::update(THD *thd, set_var *var)
{
ulong tmp= var->value->val_int();
LEX_STRING *base_name= &var->base;
if (!base_name->length)
base_name= &default_key_cache_base;
KEY_CACHE_VAR *key_cache= get_key_cache(base_name);
if (!key_cache && !(key_cache= create_key_cache(base_name->str,
base_name->length)))
return 1;
key_cache->division_limit=
(ulong) getopt_ull_limit_value(tmp, option_limits);
pthread_mutex_unlock(&LOCK_global_system_variables);
if (key_cache->cache)
/* Do not build a new key cache here */
return (bool) (ha_change_key_cache_param(key_cache));
return 0;
error= (bool) (ha_resize_key_cache(key_cache));
pthread_mutex_lock(&LOCK_global_system_variables);
key_cache->in_init= 0;
end:
pthread_mutex_unlock(&LOCK_global_system_variables);
return error;
}
@ -2506,13 +2527,14 @@ gptr find_named(I_List<NAMED_LIST> *list, const char *name, uint length,
}
void delete_elements(I_List<NAMED_LIST> *list, void (*free_element)(gptr))
void delete_elements(I_List<NAMED_LIST> *list,
void (*free_element)(const char *name, gptr))
{
NAMED_LIST *element;
DBUG_ENTER("delete_elements");
while ((element= list->get()))
{
(*free_element)(element->data);
(*free_element)(element->name, element->data);
delete element;
}
DBUG_VOID_RETURN;
@ -2524,60 +2546,65 @@ void delete_elements(I_List<NAMED_LIST> *list, void (*free_element)(gptr))
static KEY_CACHE_VAR *create_key_cache(const char *name, uint length)
{
KEY_CACHE_VAR *key_cache;
DBUG_PRINT("info",("Creating key cache: %.*s length: %d", length, name,
length));
if (length != default_key_cache_base.length ||
memcmp(name, default_key_cache_base.str, length))
DBUG_ENTER("create_key_cache");
DBUG_PRINT("enter",("name: %.*s", length, name));
if ((key_cache= (KEY_CACHE_VAR*) my_malloc(sizeof(KEY_CACHE_VAR),
MYF(MY_ZEROFILL | MY_WME))))
{
if ((key_cache= (KEY_CACHE_VAR*) my_malloc(sizeof(KEY_CACHE_VAR),
MYF(MY_ZEROFILL | MY_WME))))
if (!new NAMED_LIST(&key_caches, name, length, (gptr) key_cache))
{
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
{
key_cache= &dflt_key_cache_var;
if (!new NAMED_LIST(&key_caches, name, length, (gptr) key_cache))
key_cache= 0;
}
return key_cache;
DBUG_RETURN(key_cache);
}
KEY_CACHE_VAR *get_or_create_key_cache(const char *name, uint length)
{
LEX_STRING key_cache_name;
KEY_CACHE_VAR *key_cache;
key_cache_name.str= (char *) name;
key_cache_name.length= length;
KEY_CACHE_VAR *key_cache= get_key_cache(&key_cache_name);
if (!key_cache)
pthread_mutex_lock(&LOCK_global_system_variables);
if (!(key_cache= get_key_cache(&key_cache_name)))
key_cache= create_key_cache(name, length);
pthread_mutex_unlock(&LOCK_global_system_variables);
return key_cache;
}
void free_key_cache(gptr key_cache)
void free_key_cache(const char *name, KEY_CACHE_VAR *key_cache)
{
if (key_cache != (gptr) &dflt_key_cache_var)
my_free(key_cache, MYF(0));
ha_end_key_cache(key_cache);
my_free((char*) key_cache, MYF(0));
}
bool process_key_caches(int (* func) (KEY_CACHE_VAR *))
{
bool process_key_caches(int (* func) (const char *name, KEY_CACHE_VAR *))
{
I_List_iterator<NAMED_LIST> it(key_caches);
NAMED_LIST *element;
while ((element= it++))
{
KEY_CACHE_VAR *key_cache= (KEY_CACHE_VAR *) element->data;
if (key_cache != &dflt_key_cache_var)
func(key_cache);
func(element->name, key_cache);
}
return 0;
}

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

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