Commit 84480383 authored by unknown's avatar unknown

Fixes for MERGE TABLES and HEAP tables


Docs/manual.texi:
  Updated MERGE table stuff + more
extra/perror.c:
  Added missing error messages
include/myisammrg.h:
  Fixes for MERGE TABLE
include/queues.h:
  Fixes for MERGE TABLE
isam/isamlog.c:
  Fixed hard bug
myisam/mi_log.c:
  cleanup
myisam/mi_open.c:
  Fixed file name format in myisam log
myisam/myisamlog.c:
  Bug fixes
myisammrg/mymrgdef.h:
  Fixes for MERGE TABLE
myisammrg/myrg_create.c:
  Fixes for MERGE TABLE
myisammrg/myrg_open.c:
  Fixes for MERGE TABLE
myisammrg/myrg_queue.c:
  Fixes for MERGE TABLE
myisammrg/myrg_rfirst.c:
  Fixes for MERGE TABLE
myisammrg/myrg_rkey.c:
  Fixes for MERGE TABLE
myisammrg/myrg_rlast.c:
  Fixes for MERGE TABLE
myisammrg/myrg_rnext.c:
  Fixes for MERGE TABLE
myisammrg/myrg_rprev.c:
  Fixes for MERGE TABLE
myisammrg/myrg_rrnd.c:
  Fixes for MERGE TABLE
mysql.proj:
  update
mysys/queues.c:
  Fixed bug when using reverse queues
sql-bench/test-insert.sh:
  Separated some things to get better timings
sql/ha_heap.cc:
  Fixed heap table bug
sql/ha_heap.h:
  Fixed heap table bug
sql/ha_myisam.h:
  Fixed wrong max_keys
sql/ha_myisammrg.cc:
  Fixed MERGE TABLES
sql/ha_myisammrg.h:
  Fixed MERGE TABLES
sql/handler.h:
  Fix for MERGE TABLES and HEAP tables
sql/lex.h:
  Fixed MERGE TABLES
sql/mysql_priv.h:
  Cleanup of code
sql/sql_acl.cc:
  Fixed that privilege tables are flushed at start
sql/sql_lex.h:
  Fixed MERGE TABLES
sql/sql_parse.cc:
  Fixed MERGE TABLES
sql/sql_select.cc:
  Fixes for HEAP tables
sql/sql_table.cc:
  Cleanup
sql/sql_yacc.yy:
  Fixed MERGE TABLES
parent 462f6c94
This diff is collapsed.
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
/* Return error-text for system error messages and nisam messages */ /* Return error-text for system error messages and nisam messages */
#define PERROR_VERSION "2.2" #define PERROR_VERSION "2.3"
#include <global.h> #include <global.h>
#include <my_sys.h> #include <my_sys.h>
...@@ -59,9 +59,11 @@ static HA_ERRORS ha_errlist[]= ...@@ -59,9 +59,11 @@ static HA_ERRORS ha_errlist[]=
{ 136,"No more room in index file" }, { 136,"No more room in index file" },
{ 137,"No more records (read after end of file)" }, { 137,"No more records (read after end of file)" },
{ 138,"Unsupported extension used for table" }, { 138,"Unsupported extension used for table" },
{ 139,"Too big row (>= 24 M)"}, { 139,"Too big row (>= 16 M)"},
{ 140,"Wrong create options"}, { 140,"Wrong create options"},
{ 141,"Dupplicate unique on write or update"}, { 141,"Duplicate unique on write or update"},
{ 142,"Unknown character set used"},
{ 143,"Conflicting table definition between MERGE and mapped table"},
{ 0,NullS }, { 0,NullS },
}; };
......
...@@ -83,7 +83,8 @@ extern int myrg_rsame(MYRG_INFO *file,byte *record,int inx); ...@@ -83,7 +83,8 @@ extern int myrg_rsame(MYRG_INFO *file,byte *record,int inx);
extern int myrg_update(MYRG_INFO *file,const byte *old,byte *new_rec); extern int myrg_update(MYRG_INFO *file,const byte *old,byte *new_rec);
extern int myrg_status(MYRG_INFO *file,MYMERGE_INFO *x,int flag); extern int myrg_status(MYRG_INFO *file,MYMERGE_INFO *x,int flag);
extern int myrg_lock_database(MYRG_INFO *file,int lock_type); extern int myrg_lock_database(MYRG_INFO *file,int lock_type);
extern int myrg_create(const char *name,const char **table_names); extern int myrg_create(const char *name,const char **table_names,
my_bool fix_names);
extern int myrg_extra(MYRG_INFO *file,enum ha_extra_function function); extern int myrg_extra(MYRG_INFO *file,enum ha_extra_function function);
extern ha_rows myrg_records_in_range(MYRG_INFO *info,int inx, extern ha_rows myrg_records_in_range(MYRG_INFO *info,int inx,
const byte *start_key,uint start_key_len, const byte *start_key,uint start_key_len,
......
...@@ -53,6 +53,7 @@ void delete_queue(QUEUE *queue); ...@@ -53,6 +53,7 @@ void delete_queue(QUEUE *queue);
void queue_insert(QUEUE *queue,byte *element); void queue_insert(QUEUE *queue,byte *element);
byte *queue_remove(QUEUE *queue,uint idx); byte *queue_remove(QUEUE *queue,uint idx);
void _downheap(QUEUE *queue,uint idx); void _downheap(QUEUE *queue,uint idx);
#define is_queue_inited(queue) ((queue)->root != 0)
#ifdef __cplusplus #ifdef __cplusplus
} }
......
...@@ -246,7 +246,7 @@ register char ***argv; ...@@ -246,7 +246,7 @@ register char ***argv;
/* Fall through */ /* Fall through */
case 'I': case 'I':
case '?': case '?':
printf("%s Ver 3.1 for %s at %s\n",my_progname,SYSTEM_TYPE, printf("%s Ver 3.2 for %s at %s\n",my_progname,SYSTEM_TYPE,
MACHINE_TYPE); MACHINE_TYPE);
puts("TCX Datakonsult AB, by Monty, for your professional use\n"); puts("TCX Datakonsult AB, by Monty, for your professional use\n");
if (version) if (version)
...@@ -325,7 +325,7 @@ static int examine_log(my_string file_name, char **table_names) ...@@ -325,7 +325,7 @@ static int examine_log(my_string file_name, char **table_names)
init_io_cache(&cache,file,0,READ_CACHE,start_offset,0,MYF(0)); init_io_cache(&cache,file,0,READ_CACHE,start_offset,0,MYF(0));
bzero((gptr) com_count,sizeof(com_count)); bzero((gptr) com_count,sizeof(com_count));
init_tree(&tree,0,sizeof(file_info),(qsort_cmp) file_info_compare,0, init_tree(&tree,0,sizeof(file_info),(qsort_cmp) file_info_compare,1,
(void(*)(void*)) file_info_free); (void(*)(void*)) file_info_free);
VOID(init_key_cache(KEY_CACHE_SIZE,(uint) (10*4*(IO_SIZE+MALLOC_OVERHEAD)))); VOID(init_key_cache(KEY_CACHE_SIZE,(uint) (10*4*(IO_SIZE+MALLOC_OVERHEAD))));
......
...@@ -69,7 +69,8 @@ int mi_log(int activate_log) ...@@ -69,7 +69,8 @@ int mi_log(int activate_log)
/* Logging of records and commands on logfile */ /* Logging of records and commands on logfile */
/* All logs starts with command(1) dfile(2) process(4) result(2) */ /* All logs starts with command(1) dfile(2) process(4) result(2) */
void _myisam_log(enum myisam_log_commands command, MI_INFO *info, const byte *buffert, uint length) void _myisam_log(enum myisam_log_commands command, MI_INFO *info,
const byte *buffert, uint length)
{ {
char buff[11]; char buff[11];
int error,old_errno; int error,old_errno;
......
...@@ -524,7 +524,11 @@ MI_INFO *mi_open(const char *name, int mode, uint handle_locking) ...@@ -524,7 +524,11 @@ MI_INFO *mi_open(const char *name, int mode, uint handle_locking)
myisam_open_list=list_add(myisam_open_list,&m_info->open_list); myisam_open_list=list_add(myisam_open_list,&m_info->open_list);
pthread_mutex_unlock(&THR_LOCK_myisam); pthread_mutex_unlock(&THR_LOCK_myisam);
myisam_log(MI_LOG_OPEN,m_info,share->filename,(uint) strlen(share->filename)); if (myisam_log_file >= 0)
{
intern_filename(name_buff,share->filename);
_myisam_log(MI_LOG_OPEN,m_info,name_buff,(uint) strlen(name_buff));
}
DBUG_RETURN(m_info); DBUG_RETURN(m_info);
err: err:
......
...@@ -70,7 +70,7 @@ static void printf_log(const char *str,...); ...@@ -70,7 +70,7 @@ static void printf_log(const char *str,...);
static bool cmp_filename(struct file_info *file_info,my_string name); static bool cmp_filename(struct file_info *file_info,my_string name);
static uint verbose=0,update=0,test_info=0,max_files=0,re_open_count=0, static uint verbose=0,update=0,test_info=0,max_files=0,re_open_count=0,
recover=0,prefix_remove=0; recover=0,prefix_remove=0,opt_processes=0;
static my_string log_filename=0,filepath=0,write_filename=0,record_pos_file=0; static my_string log_filename=0,filepath=0,write_filename=0,record_pos_file=0;
static ulong com_count[10][3],number_of_commands=(ulong) ~0L, static ulong com_count[10][3],number_of_commands=(ulong) ~0L,
isamlog_process; isamlog_process;
...@@ -199,6 +199,9 @@ static void get_options(register int *argc, register char ***argv) ...@@ -199,6 +199,9 @@ static void get_options(register int *argc, register char ***argv)
update=1; update=1;
recover++; recover++;
break; break;
case 'P':
opt_processes=1;
break;
case 'R': case 'R':
if (! *++pos) if (! *++pos)
{ {
...@@ -243,7 +246,7 @@ static void get_options(register int *argc, register char ***argv) ...@@ -243,7 +246,7 @@ static void get_options(register int *argc, register char ***argv)
/* Fall through */ /* Fall through */
case 'I': case 'I':
case '?': case '?':
printf("%s Ver 1.1 for %s at %s\n",my_progname,SYSTEM_TYPE, printf("%s Ver 1.2 for %s at %s\n",my_progname,SYSTEM_TYPE,
MACHINE_TYPE); MACHINE_TYPE);
puts("By Monty, for your professional use\n"); puts("By Monty, for your professional use\n");
if (version) if (version)
...@@ -258,6 +261,7 @@ static void get_options(register int *argc, register char ***argv) ...@@ -258,6 +261,7 @@ static void get_options(register int *argc, register char ***argv)
puts(" -o \"offset\" -p # \"remove # components from path\""); puts(" -o \"offset\" -p # \"remove # components from path\"");
puts(" -r \"recover\" -R \"file recordposition\""); puts(" -r \"recover\" -R \"file recordposition\"");
puts(" -u \"update\" -v \"verbose\" -w \"write file\""); puts(" -u \"update\" -v \"verbose\" -w \"write file\"");
puts(" -P \"processes\"");
puts("\nOne can give a second and a third '-v' for more verbose."); puts("\nOne can give a second and a third '-v' for more verbose.");
puts("Normaly one does a update (-u)."); puts("Normaly one does a update (-u).");
puts("If a recover is done all writes and all possibly updates and deletes is done\nand errors are only counted."); puts("If a recover is done all writes and all possibly updates and deletes is done\nand errors are only counted.");
...@@ -322,7 +326,7 @@ static int examine_log(my_string file_name, char **table_names) ...@@ -322,7 +326,7 @@ static int examine_log(my_string file_name, char **table_names)
init_io_cache(&cache,file,0,READ_CACHE,start_offset,0,MYF(0)); init_io_cache(&cache,file,0,READ_CACHE,start_offset,0,MYF(0));
bzero((gptr) com_count,sizeof(com_count)); bzero((gptr) com_count,sizeof(com_count));
init_tree(&tree,0,sizeof(file_info),(qsort_cmp) file_info_compare,0, init_tree(&tree,0,sizeof(file_info),(qsort_cmp) file_info_compare,1,
(void(*)(void*)) file_info_free); (void(*)(void*)) file_info_free);
VOID(init_key_cache(KEY_CACHE_SIZE,(uint) (10*4*(IO_SIZE+MALLOC_OVERHEAD)))); VOID(init_key_cache(KEY_CACHE_SIZE,(uint) (10*4*(IO_SIZE+MALLOC_OVERHEAD))));
...@@ -333,6 +337,8 @@ static int examine_log(my_string file_name, char **table_names) ...@@ -333,6 +337,8 @@ static int examine_log(my_string file_name, char **table_names)
isamlog_filepos=my_b_tell(&cache)-9L; isamlog_filepos=my_b_tell(&cache)-9L;
file_info.filenr= mi_uint2korr(head+1); file_info.filenr= mi_uint2korr(head+1);
isamlog_process=file_info.process=(long) mi_uint4korr(head+3); isamlog_process=file_info.process=(long) mi_uint4korr(head+3);
if (!opt_processes)
file_info.process=0;
result= mi_uint2korr(head+7); result= mi_uint2korr(head+7);
if ((curr_file_info=(struct file_info*) tree_search(&tree,&file_info))) if ((curr_file_info=(struct file_info*) tree_search(&tree,&file_info)))
{ {
...@@ -374,11 +380,17 @@ static int examine_log(my_string file_name, char **table_names) ...@@ -374,11 +380,17 @@ static int examine_log(my_string file_name, char **table_names)
goto err; goto err;
{ {
uint i; uint i;
char *pos=file_info.name,*to; char *pos,*to;
/* Fix if old DOS files to new format */
for (pos=file_info.name; pos=strchr(pos,'\\') ; pos++)
*pos= '/';
pos=file_info.name;
for (i=0 ; i < prefix_remove ; i++) for (i=0 ; i < prefix_remove ; i++)
{ {
char *next; char *next;
if (!(next=strchr(pos,FN_LIBCHAR))) if (!(next=strchr(pos,'/')))
break; break;
pos=next+1; pos=next+1;
} }
...@@ -436,7 +448,7 @@ static int examine_log(my_string file_name, char **table_names) ...@@ -436,7 +448,7 @@ static int examine_log(my_string file_name, char **table_names)
if (file_info.used) if (file_info.used)
{ {
if (verbose && !record_pos_file) if (verbose && !record_pos_file)
printf_log("%s: open",file_info.show_name); printf_log("%s: open -> %d",file_info.show_name, file_info.filenr);
com_count[command][0]++; com_count[command][0]++;
if (result) if (result)
com_count[command][1]++; com_count[command][1]++;
......
...@@ -29,4 +29,4 @@ extern pthread_mutex_t THR_LOCK_open; ...@@ -29,4 +29,4 @@ extern pthread_mutex_t THR_LOCK_open;
#endif #endif
int _myrg_init_queue(MYRG_INFO *info,int inx,enum ha_rkey_function search_flag); int _myrg_init_queue(MYRG_INFO *info,int inx,enum ha_rkey_function search_flag);
int _myrg_finish_scan(MYRG_INFO *info, int inx, enum ha_rkey_function type);
...@@ -23,8 +23,7 @@ ...@@ -23,8 +23,7 @@
a NULL-pointer last a NULL-pointer last
*/ */
int myrg_create(name,table_names) int myrg_create(const char *name, const char **table_names, my_bool fix_names)
const char *name,**table_names;
{ {
int save_errno; int save_errno;
uint errpos; uint errpos;
...@@ -38,15 +37,19 @@ const char *name,**table_names; ...@@ -38,15 +37,19 @@ const char *name,**table_names;
goto err; goto err;
errpos=1; errpos=1;
if (table_names) if (table_names)
{
for ( ; *table_names ; table_names++) for ( ; *table_names ; table_names++)
{ {
strmov(buff,*table_names); strmov(buff,*table_names);
fn_same(buff,name,4); if (fix_names)
fn_same(buff,name,4);
*(end=strend(buff))='\n'; *(end=strend(buff))='\n';
if (my_write(file,*table_names,(uint) (end-buff+1), end[1]=0;
if (my_write(file,buff,(uint) (end-buff+1),
MYF(MY_WME | MY_NABP))) MYF(MY_WME | MY_NABP)))
goto err; goto err;
} }
}
if (my_close(file,MYF(0))) if (my_close(file,MYF(0)))
goto err; goto err;
DBUG_RETURN(0); DBUG_RETURN(0);
......
...@@ -58,7 +58,7 @@ int handle_locking; ...@@ -58,7 +58,7 @@ int handle_locking;
{ {
if ((end=strend(buff))[-1] == '\n') if ((end=strend(buff))[-1] == '\n')
end[-1]='\0'; end[-1]='\0';
if (buff[0]) /* Skipp empty lines */ if (buff[0] && buff[0] != '#') /* Skipp empty lines and comments */
{ {
last_isam=isam; last_isam=isam;
if (!test_if_hard_path(buff)) if (!test_if_hard_path(buff))
...@@ -93,7 +93,7 @@ int handle_locking; ...@@ -93,7 +93,7 @@ int handle_locking;
m_info->options|=isam->s->options; m_info->options|=isam->s->options;
m_info->records+=isam->state->records; m_info->records+=isam->state->records;
m_info->del+=isam->state->del; m_info->del+=isam->state->del;
m_info->data_file_length=isam->state->data_file_length; m_info->data_file_length+=isam->state->data_file_length;
if (i) if (i)
isam=(MI_INFO*) (isam->open_list.next->data); isam=(MI_INFO*) (isam->open_list.next->data);
} }
......
...@@ -23,31 +23,32 @@ static int queue_key_cmp(void *keyseg, byte *a, byte *b) ...@@ -23,31 +23,32 @@ static int queue_key_cmp(void *keyseg, byte *a, byte *b)
MI_INFO *aa=((MYRG_TABLE *)a)->table; MI_INFO *aa=((MYRG_TABLE *)a)->table;
MI_INFO *bb=((MYRG_TABLE *)b)->table; MI_INFO *bb=((MYRG_TABLE *)b)->table;
uint not_used; uint not_used;
int ret= _mi_key_cmp((MI_KEYSEG *)keyseg, aa->lastkey, bb->lastkey,
return (_mi_key_cmp((MI_KEYSEG *)keyseg, aa->lastkey, bb->lastkey, USE_WHOLE_KEY, SEARCH_FIND, &not_used);
USE_WHOLE_KEY, SEARCH_FIND, &not_used)); return ret < 0 ? -1 : ret > 0 ? 1 : 0;
} /* queue_key_cmp */ } /* queue_key_cmp */
int _myrg_init_queue(MYRG_INFO *info,int inx,enum ha_rkey_function search_flag) int _myrg_init_queue(MYRG_INFO *info,int inx,enum ha_rkey_function search_flag)
{ {
QUEUE *q=&(info->by_key); int error=0;
QUEUE *q= &(info->by_key);
if (!q->root) if (!is_queue_inited(q))
{ {
if (init_queue(q,info->tables, 0, if (init_queue(q,info->tables, 0,
(myisam_read_vec[search_flag]==SEARCH_SMALLER), (myisam_readnext_vec[search_flag] == SEARCH_SMALLER),
queue_key_cmp, queue_key_cmp,
info->open_tables->table->s->keyinfo[inx].seg)) info->open_tables->table->s->keyinfo[inx].seg))
return my_errno; error=my_errno;
} }
else else
{ {
if (reinit_queue(q,info->tables, 0, if (reinit_queue(q,info->tables, 0,
(myisam_read_vec[search_flag]==SEARCH_SMALLER), (myisam_readnext_vec[search_flag] == SEARCH_SMALLER),
queue_key_cmp, queue_key_cmp,
info->open_tables->table->s->keyinfo[inx].seg)) info->open_tables->table->s->keyinfo[inx].seg))
return my_errno; error=my_errno;
} }
return 0; return error;
} }
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
#include "mymrgdef.h" #include "mymrgdef.h"
/* Read first row through a specfic key */ /* Read first row according to specific key */
int myrg_rfirst(MYRG_INFO *info, byte *buf, int inx) int myrg_rfirst(MYRG_INFO *info, byte *buf, int inx)
{ {
...@@ -29,17 +29,17 @@ int myrg_rfirst(MYRG_INFO *info, byte *buf, int inx) ...@@ -29,17 +29,17 @@ int myrg_rfirst(MYRG_INFO *info, byte *buf, int inx)
for (table=info->open_tables ; table < info->end_table ; table++) for (table=info->open_tables ; table < info->end_table ; table++)
{ {
err=mi_rfirst(table->table,NULL,inx); if ((err=mi_rfirst(table->table,NULL,inx)))
info->last_used_table=table; {
if (err == HA_ERR_END_OF_FILE)
if (err == HA_ERR_END_OF_FILE) continue;
continue;
if (err)
return err; return err;
}
/* adding to queue */ /* adding to queue */
queue_insert(&(info->by_key),(byte *)table); queue_insert(&(info->by_key),(byte *)table);
} }
/* We have done a read in all tables */
info->last_used_table=table;
if (!info->by_key.elements) if (!info->by_key.elements)
return HA_ERR_END_OF_FILE; return HA_ERR_END_OF_FILE;
......
...@@ -16,6 +16,17 @@ ...@@ -16,6 +16,17 @@
/* Read record based on a key */ /* Read record based on a key */
/*
* HA_READ_KEY_EXACT => SEARCH_BIGGER
* HA_READ_KEY_OR_NEXT => SEARCH_BIGGER
* HA_READ_AFTER_KEY => SEARCH_BIGGER
* HA_READ_PREFIX => SEARCH_BIGGER
* HA_READ_KEY_OR_PREV => SEARCH_SMALLER
* HA_READ_BEFORE_KEY => SEARCH_SMALLER
* HA_READ_PREFIX_LAST => SEARCH_SMALLER
*/
#include "mymrgdef.h" #include "mymrgdef.h"
/* todo: we could store some additional info to speedup lookups: /* todo: we could store some additional info to speedup lookups:
...@@ -33,7 +44,7 @@ int myrg_rkey(MYRG_INFO *info,byte *record,int inx, const byte *key, ...@@ -33,7 +44,7 @@ int myrg_rkey(MYRG_INFO *info,byte *record,int inx, const byte *key,
MYRG_TABLE *table; MYRG_TABLE *table;
MI_INFO *mi; MI_INFO *mi;
int err; int err;
byte *buf=((search_flag == HA_READ_KEY_EXACT)?record:0); byte *buf=((search_flag == HA_READ_KEY_EXACT) ? record: 0);
if (_myrg_init_queue(info,inx,search_flag)) if (_myrg_init_queue(info,inx,search_flag))
return my_errno; return my_errno;
...@@ -52,13 +63,14 @@ int myrg_rkey(MYRG_INFO *info,byte *record,int inx, const byte *key, ...@@ -52,13 +63,14 @@ int myrg_rkey(MYRG_INFO *info,byte *record,int inx, const byte *key,
{ {
err=_mi_rkey(mi,buf,inx,key_buff,pack_key_length,search_flag,FALSE); err=_mi_rkey(mi,buf,inx,key_buff,pack_key_length,search_flag,FALSE);
} }
info->last_used_table=table; info->last_used_table=table+1;
if (err == HA_ERR_KEY_NOT_FOUND)
continue;
if (err) if (err)
{
if (err == HA_ERR_KEY_NOT_FOUND)
continue;
return err; return err;
}
/* adding to queue */ /* adding to queue */
queue_insert(&(info->by_key),(byte *)table); queue_insert(&(info->by_key),(byte *)table);
...@@ -76,14 +88,3 @@ int myrg_rkey(MYRG_INFO *info,byte *record,int inx, const byte *key, ...@@ -76,14 +88,3 @@ int myrg_rkey(MYRG_INFO *info,byte *record,int inx, const byte *key,
mi=(info->current_table=(MYRG_TABLE *)queue_top(&(info->by_key)))->table; mi=(info->current_table=(MYRG_TABLE *)queue_top(&(info->by_key)))->table;
return mi_rrnd(mi,record,mi->lastpos); return mi_rrnd(mi,record,mi->lastpos);
} }
/*
* HA_READ_KEY_EXACT => SEARCH_BIGGER
* HA_READ_KEY_OR_NEXT => SEARCH_BIGGER
* HA_READ_AFTER_KEY => SEARCH_BIGGER
* HA_READ_PREFIX => SEARCH_BIGGER
* HA_READ_KEY_OR_PREV => SEARCH_SMALLER
* HA_READ_BEFORE_KEY => SEARCH_SMALLER
* HA_READ_PREFIX_LAST => SEARCH_SMALLER
*/
...@@ -24,22 +24,22 @@ int myrg_rlast(MYRG_INFO *info, byte *buf, int inx) ...@@ -24,22 +24,22 @@ int myrg_rlast(MYRG_INFO *info, byte *buf, int inx)
MI_INFO *mi; MI_INFO *mi;
int err; int err;
if (_myrg_init_queue(info,inx,HA_READ_KEY_OR_PREV)) if (_myrg_init_queue(info,inx, HA_READ_KEY_OR_PREV))
return my_errno; return my_errno;
for (table=info->open_tables ; table < info->end_table ; table++) for (table=info->open_tables ; table < info->end_table ; table++)
{ {
err=mi_rlast(table->table,NULL,inx); if ((err=mi_rlast(table->table,NULL,inx)))
info->last_used_table=table; {
if (err == HA_ERR_END_OF_FILE)
if (err == HA_ERR_END_OF_FILE) continue;
continue;
if (err)
return err; return err;
}
/* adding to queue */ /* adding to queue */
queue_insert(&(info->by_key),(byte *)table); queue_insert(&(info->by_key),(byte *)table);
} }
/* We have done a read in all tables */
info->last_used_table=table;
if (!info->by_key.elements) if (!info->by_key.elements)
return HA_ERR_END_OF_FILE; return HA_ERR_END_OF_FILE;
......
...@@ -22,22 +22,21 @@ ...@@ -22,22 +22,21 @@
int myrg_rnext(MYRG_INFO *info, byte *buf, int inx) int myrg_rnext(MYRG_INFO *info, byte *buf, int inx)
{ {
MYRG_TABLE *table;
MI_INFO *mi;
byte *key_buff;
uint pack_key_length;
int err; int err;
MI_INFO *mi;
/* at first, do rnext for the table found before */ /* at first, do rnext for the table found before */
err=mi_rnext(info->current_table->table,NULL,inx); if ((err=mi_rnext(info->current_table->table,NULL,inx)))
if (err == HA_ERR_END_OF_FILE)
{ {
queue_remove(&(info->by_key),0); if (err == HA_ERR_END_OF_FILE)
if (!info->by_key.elements) {
return HA_ERR_END_OF_FILE; queue_remove(&(info->by_key),0);
if (!info->by_key.elements)
return HA_ERR_END_OF_FILE;
}
else
return err;
} }
else if (err)
return err;
else else
{ {
/* Found here, adding to queue */ /* Found here, adding to queue */
...@@ -46,30 +45,42 @@ int myrg_rnext(MYRG_INFO *info, byte *buf, int inx) ...@@ -46,30 +45,42 @@ int myrg_rnext(MYRG_INFO *info, byte *buf, int inx)
} }
/* next, let's finish myrg_rkey's initial scan */ /* next, let's finish myrg_rkey's initial scan */
table=info->last_used_table+1; if ((err=_myrg_finish_scan(info, inx, HA_READ_KEY_OR_NEXT)))
return err;
/* now, mymerge's read_next is as simple as one queue_top */
mi=(info->current_table=(MYRG_TABLE *)queue_top(&(info->by_key)))->table;
return mi_rrnd(mi,buf,mi->lastpos);
}
/* let's finish myrg_rkey's initial scan */
int _myrg_finish_scan(MYRG_INFO *info, int inx, enum ha_rkey_function type)
{
int err;
MYRG_TABLE *table=info->last_used_table;
if (table < info->end_table) if (table < info->end_table)
{ {
mi=info->last_used_table->table; MI_INFO *mi= table[-1].table;
key_buff=(byte*) mi->lastkey+mi->s->base.max_key_length; byte *key_buff=(byte*) mi->lastkey+mi->s->base.max_key_length;
pack_key_length=mi->last_rkey_length; uint pack_key_length= mi->last_rkey_length;
for (; table < info->end_table ; table++) for (; table < info->end_table ; table++)
{ {
mi=table->table; mi=table->table;
err=_mi_rkey(mi,NULL,inx,key_buff,pack_key_length,HA_READ_KEY_OR_NEXT,FALSE); if ((err=_mi_rkey(mi,NULL,inx,key_buff,pack_key_length,
info->last_used_table=table; type,FALSE)))
{
if (err == HA_ERR_KEY_NOT_FOUND) if (err == HA_ERR_KEY_NOT_FOUND) /* If end of file */
continue; continue;
if (err) return err;
return err; }
/* Found here, adding to queue */ /* Found here, adding to queue */
queue_insert(&(info->by_key),(byte *)table); queue_insert(&(info->by_key),(byte *) table);
} }
/* All tables are now used */
info->last_used_table=table;
} }
return 0;
/* now, mymerge's read_next is as simple as one queue_top */
mi=(info->current_table=(MYRG_TABLE *)queue_top(&(info->by_key)))->table;
return mi_rrnd(mi,buf,mi->lastpos);
} }
...@@ -22,22 +22,21 @@ ...@@ -22,22 +22,21 @@
int myrg_rprev(MYRG_INFO *info, byte *buf, int inx) int myrg_rprev(MYRG_INFO *info, byte *buf, int inx)
{ {
MYRG_TABLE *table;
MI_INFO *mi;
byte *key_buff;
uint pack_key_length;
int err; int err;
MI_INFO *mi;
/* at first, do rnext for the table found before */ /* at first, do rprev for the table found before */
err=mi_rprev(info->current_table->table,NULL,inx); if ((err=mi_rprev(info->current_table->table,NULL,inx)))
if (err == HA_ERR_END_OF_FILE)
{ {
queue_remove(&(info->by_key),0); if (err == HA_ERR_END_OF_FILE)
if (!info->by_key.elements) {
return HA_ERR_END_OF_FILE; queue_remove(&(info->by_key),0);
if (!info->by_key.elements)
return HA_ERR_END_OF_FILE;
}
else
return err;
} }
else if (err)
return err;
else else
{ {
/* Found here, adding to queue */ /* Found here, adding to queue */
...@@ -46,28 +45,8 @@ int myrg_rprev(MYRG_INFO *info, byte *buf, int inx) ...@@ -46,28 +45,8 @@ int myrg_rprev(MYRG_INFO *info, byte *buf, int inx)
} }
/* next, let's finish myrg_rkey's initial scan */ /* next, let's finish myrg_rkey's initial scan */
table=info->last_used_table+1; if ((err=_myrg_finish_scan(info, inx, HA_READ_KEY_OR_PREV)))
if (table < info->end_table) return err;
{
mi=info->last_used_table->table;
key_buff=(byte*) mi->lastkey+mi->s->base.max_key_length;
pack_key_length=mi->last_rkey_length;
for (; table < info->end_table ; table++)
{
mi=table->table;
err=_mi_rkey(mi,NULL,inx,key_buff,pack_key_length,
HA_READ_KEY_OR_PREV,FALSE);
info->last_used_table=table;
if (err == HA_ERR_KEY_NOT_FOUND)
continue;
if (err)
return err;
/* Found here, adding to queue */
queue_insert(&(info->by_key),(byte *)table);
}
}
/* now, mymerge's read_prev is as simple as one queue_top */ /* now, mymerge's read_prev is as simple as one queue_top */
mi=(info->current_table=(MYRG_TABLE *)queue_top(&(info->by_key)))->table; mi=(info->current_table=(MYRG_TABLE *)queue_top(&(info->by_key)))->table;
......
...@@ -84,10 +84,10 @@ int myrg_rrnd(MYRG_INFO *info,byte *buf,ulonglong filepos) ...@@ -84,10 +84,10 @@ int myrg_rrnd(MYRG_INFO *info,byte *buf,ulonglong filepos)
info->end_table-1,filepos); info->end_table-1,filepos);
isam_info=info->current_table->table; isam_info=info->current_table->table;
isam_info->update&= HA_STATE_CHANGED; isam_info->update&= HA_STATE_CHANGED;
return ((*isam_info->s->read_rnd)(isam_info,(byte*) buf, return ((*isam_info->s->read_rnd)
(ha_rows) (filepos - (isam_info, (byte*) buf,
info->current_table->file_offset), (ha_rows) (filepos - info->current_table->file_offset),
0)); 0));
} }
......
No preview for this file type
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
#include <queues.h> #include <queues.h>
/* The actuall code for handling queues */ /* Init queue */
int init_queue(QUEUE *queue, uint max_elements, uint offset_to_key, int init_queue(QUEUE *queue, uint max_elements, uint offset_to_key,
pbool max_at_top, int (*compare) (void *, byte *, byte *), pbool max_at_top, int (*compare) (void *, byte *, byte *),
...@@ -44,6 +44,12 @@ int init_queue(QUEUE *queue, uint max_elements, uint offset_to_key, ...@@ -44,6 +44,12 @@ int init_queue(QUEUE *queue, uint max_elements, uint offset_to_key,
DBUG_RETURN(0); DBUG_RETURN(0);
} }
/*
Reinitialize queue for new usage; Note that you can't currently resize
the number of elements! If you need this, fix it :)
*/
int reinit_queue(QUEUE *queue, uint max_elements, uint offset_to_key, int reinit_queue(QUEUE *queue, uint max_elements, uint offset_to_key,
pbool max_at_top, int (*compare) (void *, byte *, byte *), pbool max_at_top, int (*compare) (void *, byte *, byte *),
void *first_cmp_arg) void *first_cmp_arg)
...@@ -78,6 +84,7 @@ void delete_queue(QUEUE *queue) ...@@ -78,6 +84,7 @@ void delete_queue(QUEUE *queue)
void queue_insert(register QUEUE *queue, byte *element) void queue_insert(register QUEUE *queue, byte *element)
{ {
reg2 uint idx,next; reg2 uint idx,next;
int cmp;
#ifndef DBUG_OFF #ifndef DBUG_OFF
if (queue->elements < queue->max_elements) if (queue->elements < queue->max_elements)
...@@ -86,10 +93,12 @@ void queue_insert(register QUEUE *queue, byte *element) ...@@ -86,10 +93,12 @@ void queue_insert(register QUEUE *queue, byte *element)
queue->root[0]=element; queue->root[0]=element;
idx= ++queue->elements; idx= ++queue->elements;
while ((queue->compare(queue->first_cmp_arg, /* max_at_top swaps the comparison if we want to order by desc */
element+queue->offset_to_key, while ((cmp=queue->compare(queue->first_cmp_arg,
queue->root[(next=idx >> 1)]+queue->offset_to_key) element+queue->offset_to_key,
^ queue->max_at_top) < 0) queue->root[(next=idx >> 1)] +
queue->offset_to_key)) &&
(cmp ^ queue->max_at_top) < 0)
{ {
queue->root[idx]=queue->root[next]; queue->root[idx]=queue->root[next];
idx=next; idx=next;
......
...@@ -348,12 +348,12 @@ print " for select_diff_key ($count:$rows): " . ...@@ -348,12 +348,12 @@ print " for select_diff_key ($count:$rows): " .
# Test select that is very popular when using ODBC # Test select that is very popular when using ODBC
check_or_range("id","select_range_prefix"); check_or_range("id","select_range_prefix");
check_or_range("id3","select_range"); check_or_range("id3","select_range_key2");
# Check reading on direct key on id and id3 # Check reading on direct key on id and id3
check_select_key("id","select_key_prefix"); check_select_key("id","select_key_prefix");
check_select_key("id3","select_key"); check_select_key("id3","select_key_key2");
#### ####
#### A lot of simple selects on ranges #### A lot of simple selects on ranges
...@@ -403,7 +403,7 @@ check_select_key("id3","select_key"); ...@@ -403,7 +403,7 @@ check_select_key("id3","select_key");
print "\nTest of compares with simple ranges\n"; print "\nTest of compares with simple ranges\n";
check_select_range("id","select_range_prefix"); check_select_range("id","select_range_prefix");
check_select_range("id3","select_range"); check_select_range("id3","select_range_key2");
#### ####
#### Some group queries #### Some group queries
...@@ -1107,20 +1107,28 @@ if ($server->small_rollback_segment()) ...@@ -1107,20 +1107,28 @@ if ($server->small_rollback_segment())
# Delete everything from table # Delete everything from table
# #
print "Deleting everything from table\n"; print "Deleting rows from the table\n";
$loop_time=new Benchmark; $loop_time=new Benchmark;
$count=0; $count=0;
for ($i=0 ; $i < 128 ; $i++)
{
$dbh->do("delete from bench1 where field1 = $i") or die $DBI::errstr;
}
$end_time=new Benchmark;
print "Time for delete_big_many_keys ($count): " .
timestr(timediff($end_time, $loop_time),"all") . "\n\n";
print "Deleting everything from table\n";
$count=1;
if ($opt_fast) if ($opt_fast)
{ {
$dbh->do("delete from bench1 where field1 = 0") or die $DBI::errstr;
$dbh->do("delete from bench1") or die $DBI::errstr; $dbh->do("delete from bench1") or die $DBI::errstr;
$count+=2;
} }
else else
{ {
$dbh->do("delete from bench1 where field1 = 0") or die $DBI::errstr;
$dbh->do("delete from bench1 where field1 > 0") or die $DBI::errstr; $dbh->do("delete from bench1 where field1 > 0") or die $DBI::errstr;
$count+=2;
} }
if ($opt_lock_tables) if ($opt_lock_tables)
...@@ -1129,7 +1137,7 @@ if ($opt_lock_tables) ...@@ -1129,7 +1137,7 @@ if ($opt_lock_tables)
} }
$end_time=new Benchmark; $end_time=new Benchmark;
print "Time for delete_big_many_keys ($count): " . print "Time for delete_all_many_keys ($count): " .
timestr(timediff($end_time, $loop_time),"all") . "\n\n"; timestr(timediff($end_time, $loop_time),"all") . "\n\n";
$sth = $dbh->do("drop table bench1") or die $DBI::errstr; $sth = $dbh->do("drop table bench1") or die $DBI::errstr;
......
...@@ -261,7 +261,7 @@ ha_rows ha_heap::records_in_range(int inx, ...@@ -261,7 +261,7 @@ ha_rows ha_heap::records_in_range(int inx,
if (start_key_len != end_key_len || if (start_key_len != end_key_len ||
start_key_len != pos->key_length || start_key_len != pos->key_length ||
start_search_flag != HA_READ_KEY_EXACT || start_search_flag != HA_READ_KEY_EXACT ||
end_search_flag != HA_READ_KEY_EXACT) end_search_flag != HA_READ_AFTER_KEY)
return HA_POS_ERROR; // Can't only use exact keys return HA_POS_ERROR; // Can't only use exact keys
return 10; // Good guess return 10; // Good guess
} }
......
...@@ -33,14 +33,15 @@ class ha_heap: public handler ...@@ -33,14 +33,15 @@ class ha_heap: public handler
const char *table_type() const { return "HEAP"; } const char *table_type() const { return "HEAP"; }
const char **bas_ext() const; const char **bas_ext() const;
ulong option_flag() const ulong option_flag() const
{ return (HA_READ_RND_SAME+HA_NO_INDEX+HA_BINARY_KEYS+HA_WRONG_ASCII_ORDER+ { return (HA_READ_RND_SAME | HA_NO_INDEX | HA_ONLY_WHOLE_INDEX |
HA_KEYPOS_TO_RNDPOS+HA_NO_BLOBS+HA_REC_NOT_IN_SEQ); } HA_WRONG_ASCII_ORDER | HA_KEYPOS_TO_RNDPOS | HA_NO_BLOBS |
HA_REC_NOT_IN_SEQ); }
uint max_record_length() const { return HA_MAX_REC_LENGTH; } uint max_record_length() const { return HA_MAX_REC_LENGTH; }
uint max_keys() const { return MAX_KEY; } uint max_keys() const { return MAX_KEY; }
uint max_key_parts() const { return MAX_REF_PARTS; } uint max_key_parts() const { return MAX_REF_PARTS; }
uint max_key_length() const { return HA_MAX_REC_LENGTH; } uint max_key_length() const { return HA_MAX_REC_LENGTH; }
virtual double scan_time() { return (double) (records+deleted) / 100.0; } virtual double scan_time() { return (double) (records+deleted) / 20.0+10; }
virtual double read_time(ha_rows rows) { return (double) rows / 100.0; } virtual double read_time(ha_rows rows) { return (double) rows / 20.0+1; }
virtual bool fast_key_read() { return 1;} virtual bool fast_key_read() { return 1;}
int open(const char *name, int mode, int test_if_locked); int open(const char *name, int mode, int test_if_locked);
......
...@@ -45,7 +45,7 @@ class ha_myisam: public handler ...@@ -45,7 +45,7 @@ class ha_myisam: public handler
const char **bas_ext() const; const char **bas_ext() const;
ulong option_flag() const { return int_option_flag; } ulong option_flag() const { return int_option_flag; }
uint max_record_length() const { return HA_MAX_REC_LENGTH; } uint max_record_length() const { return HA_MAX_REC_LENGTH; }
uint max_keys() const { return 1; } uint max_keys() const { return MI_MAX_KEY; }
uint max_key_parts() const { return MAX_REF_PARTS; } uint max_key_parts() const { return MAX_REF_PARTS; }
uint max_key_length() const { return MAX_KEY_LENGTH; } uint max_key_length() const { return MAX_KEY_LENGTH; }
......
...@@ -180,11 +180,7 @@ void ha_myisammrg::info(uint flag) ...@@ -180,11 +180,7 @@ void ha_myisammrg::info(uint flag)
mean_rec_length=info.reclength; mean_rec_length=info.reclength;
block_size=0; block_size=0;
update_time=0; update_time=0;
#if SIZEOF_OFF_T > 4
ref_length=6; // Should be big enough ref_length=6; // Should be big enough
#else
ref_length=4;
#endif
} }
...@@ -228,6 +224,16 @@ THR_LOCK_DATA **ha_myisammrg::store_lock(THD *thd, ...@@ -228,6 +224,16 @@ THR_LOCK_DATA **ha_myisammrg::store_lock(THD *thd,
int ha_myisammrg::create(const char *name, register TABLE *form, int ha_myisammrg::create(const char *name, register TABLE *form,
HA_CREATE_INFO *create_info) HA_CREATE_INFO *create_info)
{ {
char buff[FN_REFLEN]; char buff[FN_REFLEN],**table_names,**pos;
return myrg_create(fn_format(buff,name,"","",2+4+16),0); TABLE_LIST *tables= (TABLE_LIST*) create_info->merge_list.first;
DBUG_ENTER("ha_myisammrg::create");
if (!(table_names= (char**) sql_alloc((create_info->merge_list.elements+1)*
sizeof(char*))))
DBUG_RETURN(1);
for (pos=table_names ; tables ; tables=tables->next)
*pos++= tables->real_name;
*pos=0;
DBUG_RETURN(myrg_create(fn_format(buff,name,"","",2+4+16),
(const char **) table_names, (my_bool) 0));
} }
...@@ -32,15 +32,19 @@ class ha_myisammrg: public handler ...@@ -32,15 +32,19 @@ class ha_myisammrg: public handler
~ha_myisammrg() {} ~ha_myisammrg() {}
const char *table_type() const { return "MRG_MyISAM"; } const char *table_type() const { return "MRG_MyISAM"; }
const char **bas_ext() const; const char **bas_ext() const;
ulong option_flag() const { return HA_REC_NOT_IN_SEQ+HA_READ_NEXT+ ulong option_flag() const
HA_READ_PREV+HA_READ_RND_SAME+HA_HAVE_KEY_READ_ONLY+ { return (HA_REC_NOT_IN_SEQ | HA_READ_NEXT |
HA_KEYPOS_TO_RNDPOS+HA_READ_ORDER+ HA_READ_PREV | HA_READ_RND_SAME |
HA_LASTKEY_ORDER+HA_READ_NOT_EXACT_KEY+ HA_HAVE_KEY_READ_ONLY |
HA_LONGLONG_KEYS+HA_NULL_KEY+HA_BLOB_KEY; } HA_KEYPOS_TO_RNDPOS | HA_READ_ORDER |
HA_LASTKEY_ORDER | HA_READ_NOT_EXACT_KEY |
HA_LONGLONG_KEYS | HA_NULL_KEY | HA_BLOB_KEY); }
uint max_record_length() const { return HA_MAX_REC_LENGTH; } uint max_record_length() const { return HA_MAX_REC_LENGTH; }
uint max_keys() const { return 1; } uint max_keys() const { return MI_MAX_KEY; }
uint max_key_parts() const { return MAX_REF_PARTS; } uint max_key_parts() const { return MAX_REF_PARTS; }
uint max_key_length() const { return MAX_KEY_LENGTH; } uint max_key_length() const { return MAX_KEY_LENGTH; }
virtual double scan_time()
{ return ulonglong2double(data_file_length) / IO_SIZE + file->tables; }
int open(const char *name, int mode, int test_if_locked); int open(const char *name, int mode, int test_if_locked);
int close(void); int close(void);
......
...@@ -47,7 +47,7 @@ ...@@ -47,7 +47,7 @@
if database is updated after read) */ if database is updated after read) */
#define HA_REC_NOT_IN_SEQ 64 /* ha_info don't return recnumber; #define HA_REC_NOT_IN_SEQ 64 /* ha_info don't return recnumber;
It returns a position to ha_r_rnd */ It returns a position to ha_r_rnd */
#define HA_BINARY_KEYS 128 /* Keys must be exact */ #define HA_ONLY_WHOLE_INDEX 128 /* Can't use part key searches */
#define HA_RSAME_NO_INDEX 256 /* RSAME can't restore index */ #define HA_RSAME_NO_INDEX 256 /* RSAME can't restore index */
#define HA_WRONG_ASCII_ORDER 512 /* Can't use sorting through key */ #define HA_WRONG_ASCII_ORDER 512 /* Can't use sorting through key */
#define HA_HAVE_KEY_READ_ONLY 1024 /* Can read only keys (no record) */ #define HA_HAVE_KEY_READ_ONLY 1024 /* Can read only keys (no record) */
...@@ -127,6 +127,7 @@ typedef struct st_ha_create_information ...@@ -127,6 +127,7 @@ typedef struct st_ha_create_information
ulong raid_chunksize; ulong raid_chunksize;
bool if_not_exists; bool if_not_exists;
ulong used_fields; ulong used_fields;
SQL_LIST merge_list;
} HA_CREATE_INFO; } HA_CREATE_INFO;
......
...@@ -297,11 +297,12 @@ static SYMBOL symbols[] = { ...@@ -297,11 +297,12 @@ static SYMBOL symbols[] = {
{ "TRAILING", SYM(TRAILING),0,0}, { "TRAILING", SYM(TRAILING),0,0},
{ "TO", SYM(TO_SYM),0,0}, { "TO", SYM(TO_SYM),0,0},
{ "TYPE", SYM(TYPE_SYM),0,0}, { "TYPE", SYM(TYPE_SYM),0,0},
{ "USE", SYM(USE_SYM),0,0}, { "UNION", SYM(UNION_SYM),0,0},
{ "USING", SYM(USING),0,0},
{ "UNIQUE", SYM(UNIQUE_SYM),0,0}, { "UNIQUE", SYM(UNIQUE_SYM),0,0},
{ "UNLOCK", SYM(UNLOCK_SYM),0,0}, { "UNLOCK", SYM(UNLOCK_SYM),0,0},
{ "UNSIGNED", SYM(UNSIGNED),0,0}, { "UNSIGNED", SYM(UNSIGNED),0,0},
{ "USE", SYM(USE_SYM),0,0},
{ "USING", SYM(USING),0,0},
{ "UPDATE", SYM(UPDATE_SYM),0,0}, { "UPDATE", SYM(UPDATE_SYM),0,0},
{ "USAGE", SYM(USAGE),0,0}, { "USAGE", SYM(USAGE),0,0},
{ "VALUES", SYM(VALUES),0,0}, { "VALUES", SYM(VALUES),0,0},
......
...@@ -78,7 +78,11 @@ void sql_element_free(void *ptr); ...@@ -78,7 +78,11 @@ void sql_element_free(void *ptr);
// The following is used to decide if MySQL should use table scanning // The following is used to decide if MySQL should use table scanning
// instead of reading with keys. The number says how many evaluation of the // instead of reading with keys. The number says how many evaluation of the
// WHERE clause is comparable to reading one extra row from a table. // WHERE clause is comparable to reading one extra row from a table.
#define TIME_FOR_COMPARE 5 // 5 compares == one read #define TIME_FOR_COMPARE 5 // 5 compares == one read
// Number of rows in a reference table when refereed through a not unique key.
// This value is only used when we don't know anything about the key
// distribution.
#define MATCHING_ROWS_IN_OTHER_TABLE 10
/* Don't pack string keys shorter than this (if PACK_KEYS=1 isn't used) */ /* Don't pack string keys shorter than this (if PACK_KEYS=1 isn't used) */
#define KEY_DEFAULT_PACK_LENGTH 8 #define KEY_DEFAULT_PACK_LENGTH 8
......
...@@ -1905,6 +1905,7 @@ int grant_init (void) ...@@ -1905,6 +1905,7 @@ int grant_init (void)
{ {
t_table->file->index_end(); t_table->file->index_end();
mysql_unlock_tables(thd, lock); mysql_unlock_tables(thd, lock);
thd->version--; // Force close to free memory
close_thread_tables(thd); close_thread_tables(thd);
delete thd; delete thd;
DBUG_RETURN(0); // Empty table is ok! DBUG_RETURN(0); // Empty table is ok!
......
...@@ -94,16 +94,9 @@ typedef struct st_lex { ...@@ -94,16 +94,9 @@ typedef struct st_lex {
LEX_YYSTYPE yylval; LEX_YYSTYPE yylval;
uchar *ptr,*tok_start,*tok_end,*end_of_query; uchar *ptr,*tok_start,*tok_end,*end_of_query;
ha_rows select_limit,offset_limit; ha_rows select_limit,offset_limit;
bool create_refs,drop_primary,drop_if_exists,local_file,
in_comment,ignore_space,verbose;
enum_sql_command sql_command;
enum lex_states next_state;
ulong options;
uint in_sum_expr,grant,grant_tot_col,which_columns, sort_default;
char *length,*dec,*change,*name; char *length,*dec,*change,*name;
String *wild; String *wild;
sql_exchange *exchange; sql_exchange *exchange;
thr_lock_type lock_option;
List<List_item> expr_list; List<List_item> expr_list;
List<List_item> when_list; List<List_item> when_list;
...@@ -124,17 +117,25 @@ typedef struct st_lex { ...@@ -124,17 +117,25 @@ typedef struct st_lex {
create_field *last_field; create_field *last_field;
Item *where,*having,*default_value; Item *where,*having,*default_value;
enum enum_duplicates duplicates;
ulong thread_id,type;
HA_CREATE_INFO create_info;
CONVERT *convert_set; CONVERT *convert_set;
LEX_USER *grant_user; LEX_USER *grant_user;
char *db,*db1,*table1,*db2,*table2; /* For outer join using .. */ char *db,*db1,*table1,*db2,*table2; /* For outer join using .. */
gptr yacc_yyss,yacc_yyvs; gptr yacc_yyss,yacc_yyvs;
THD *thd; THD *thd;
udf_func udf; udf_func udf;
HA_CHECK_OPT check_opt; // check/repair options HA_CHECK_OPT check_opt; // check/repair options
LEX_MASTER_INFO mi; // used by CHANGE MASTER HA_CREATE_INFO create_info;
LEX_MASTER_INFO mi; // used by CHANGE MASTER
ulong thread_id,type;
ulong options;
enum_sql_command sql_command;
enum lex_states next_state;
enum enum_duplicates duplicates;
uint in_sum_expr,grant,grant_tot_col,which_columns, sort_default;
thr_lock_type lock_option;
bool create_refs,drop_primary,drop_if_exists,local_file;
bool in_comment,ignore_space,verbose;
} LEX; } LEX;
......
...@@ -38,8 +38,9 @@ extern "C" pthread_mutex_t THR_LOCK_keycache; ...@@ -38,8 +38,9 @@ extern "C" pthread_mutex_t THR_LOCK_keycache;
extern "C" int gethostname(char *name, int namelen); extern "C" int gethostname(char *name, int namelen);
#endif #endif
static bool check_table_access(THD *thd,uint want_access,TABLE_LIST *tables); static bool check_table_access(THD *thd,uint want_access, TABLE_LIST *tables);
static bool check_db_used(THD *thd,TABLE_LIST *tables); static bool check_db_used(THD *thd,TABLE_LIST *tables);
static bool check_merge_table_access(THD *thd, char *db, TABLE_LIST *tables);
static bool check_dup(THD *thd,const char *db,const char *name, static bool check_dup(THD *thd,const char *db,const char *name,
TABLE_LIST *tables); TABLE_LIST *tables);
static void mysql_init_query(THD *thd); static void mysql_init_query(THD *thd);
...@@ -504,9 +505,9 @@ int mysql_table_dump(THD* thd, char* db, char* tbl_name, int fd) ...@@ -504,9 +505,9 @@ int mysql_table_dump(THD* thd, char* db, char* tbl_name, int fd)
if(!(table=open_ltable(thd, table_list, TL_READ_NO_INSERT))) if(!(table=open_ltable(thd, table_list, TL_READ_NO_INSERT)))
DBUG_RETURN(1); DBUG_RETURN(1);
if(check_access(thd, SELECT_ACL, db, &table_list->grant.privilege)) if (check_access(thd, SELECT_ACL, db, &table_list->grant.privilege))
goto err; goto err;
if(grant_option && check_grant(thd, SELECT_ACL, table_list)) if (grant_option && check_grant(thd, SELECT_ACL, table_list))
goto err; goto err;
thd->free_list = 0; thd->free_list = 0;
...@@ -988,10 +989,12 @@ mysql_execute_command(void) ...@@ -988,10 +989,12 @@ mysql_execute_command(void)
break; break;
case SQLCOM_CREATE_TABLE: case SQLCOM_CREATE_TABLE:
#ifdef DEMO_VERSION if (!tables->db)
send_error(&thd->net,ER_NOT_ALLOWED_COMMAND); tables->db=thd->db;
#else if (check_access(thd,CREATE_ACL,tables->db,&tables->grant.privilege) ||
if (check_access(thd,CREATE_ACL,tables->db,&tables->grant.privilege)) check_merge_table_access(thd, tables->db,
(TABLE_LIST *)
lex->create_info.merge_list.first))
goto error; /* purecov: inspected */ goto error; /* purecov: inspected */
if (grant_option) if (grant_option)
{ {
...@@ -1072,7 +1075,6 @@ mysql_execute_command(void) ...@@ -1072,7 +1075,6 @@ mysql_execute_command(void)
if (grant_option && check_grant(thd,INDEX_ACL,tables)) if (grant_option && check_grant(thd,INDEX_ACL,tables))
goto error; goto error;
res = mysql_create_index(thd, tables, lex->key_list); res = mysql_create_index(thd, tables, lex->key_list);
#endif
break; break;
case SQLCOM_SLAVE_START: case SQLCOM_SLAVE_START:
...@@ -1082,7 +1084,6 @@ mysql_execute_command(void) ...@@ -1082,7 +1084,6 @@ mysql_execute_command(void)
stop_slave(thd); stop_slave(thd);
break; break;
case SQLCOM_ALTER_TABLE: case SQLCOM_ALTER_TABLE:
#if defined(DONT_ALLOW_SHOW_COMMANDS) #if defined(DONT_ALLOW_SHOW_COMMANDS)
send_error(&thd->net,ER_NOT_ALLOWED_COMMAND); /* purecov: inspected */ send_error(&thd->net,ER_NOT_ALLOWED_COMMAND); /* purecov: inspected */
...@@ -1096,11 +1097,16 @@ mysql_execute_command(void) ...@@ -1096,11 +1097,16 @@ mysql_execute_command(void)
res=0; res=0;
break; break;
} }
if (!tables->db)
tables->db=thd->db;
if (!lex->db) if (!lex->db)
lex->db=tables->db; lex->db=tables->db;
if (check_access(thd,ALTER_ACL,tables->db,&tables->grant.privilege) || if (check_access(thd,ALTER_ACL,tables->db,&tables->grant.privilege) ||
check_access(thd,INSERT_ACL | CREATE_ACL,lex->db,&priv)) check_access(thd,INSERT_ACL | CREATE_ACL,lex->db,&priv) ||
goto error; /* purecov: inspected */ check_merge_table_access(thd, tables->db,
(TABLE_LIST *)
lex->create_info.merge_list.first))
goto error; /* purecov: inspected */
if (!tables->db) if (!tables->db)
tables->db=thd->db; tables->db=thd->db;
if (grant_option) if (grant_option)
...@@ -1354,7 +1360,7 @@ mysql_execute_command(void) ...@@ -1354,7 +1360,7 @@ mysql_execute_command(void)
res = mysql_drop_index(thd, tables, lex->drop_list); res = mysql_drop_index(thd, tables, lex->drop_list);
break; break;
case SQLCOM_SHOW_DATABASES: case SQLCOM_SHOW_DATABASES:
#if defined(DONT_ALLOW_SHOW_COMMANDS) || defined(DEMO_VERSION) #if defined(DONT_ALLOW_SHOW_COMMANDS)
send_error(&thd->net,ER_NOT_ALLOWED_COMMAND); /* purecov: inspected */ send_error(&thd->net,ER_NOT_ALLOWED_COMMAND); /* purecov: inspected */
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
#else #else
...@@ -1810,6 +1816,22 @@ static bool check_db_used(THD *thd,TABLE_LIST *tables) ...@@ -1810,6 +1816,22 @@ static bool check_db_used(THD *thd,TABLE_LIST *tables)
} }
static bool check_merge_table_access(THD *thd, char *db, TABLE_LIST *table_list)
{
int error=0;
if (table_list)
{
/* Force all tables to use the current database */
TABLE_LIST *tmp;
for (tmp=table_list; tmp ; tmp=tmp->next)
tmp->db=db;
error=check_table_access(thd, SELECT_ACL | UPDATE_ACL | DELETE_ACL,
table_list);
}
return error;
}
/**************************************************************************** /****************************************************************************
Check stack size; Send error if there isn't enough stack to continue Check stack size; Send error if there isn't enough stack to continue
****************************************************************************/ ****************************************************************************/
...@@ -2462,7 +2484,7 @@ static int start_slave(THD* thd , bool net_report) ...@@ -2462,7 +2484,7 @@ static int start_slave(THD* thd , bool net_report)
if(!thd) thd = current_thd; if(!thd) thd = current_thd;
NET* net = &thd->net; NET* net = &thd->net;
const char* err = 0; const char* err = 0;
if(check_access(thd, PROCESS_ACL, any_db)) if (check_access(thd, PROCESS_ACL, any_db))
return 1; return 1;
pthread_mutex_lock(&LOCK_slave); pthread_mutex_lock(&LOCK_slave);
if(!slave_running) if(!slave_running)
...@@ -2497,7 +2519,7 @@ static int stop_slave(THD* thd, bool net_report ) ...@@ -2497,7 +2519,7 @@ static int stop_slave(THD* thd, bool net_report )
NET* net = &thd->net; NET* net = &thd->net;
const char* err = 0; const char* err = 0;
if(check_access(thd, PROCESS_ACL, any_db)) if (check_access(thd, PROCESS_ACL, any_db))
return 1; return 1;
pthread_mutex_lock(&LOCK_slave); pthread_mutex_lock(&LOCK_slave);
......
...@@ -942,7 +942,7 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds, ...@@ -942,7 +942,7 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds,
} }
/* Approximate found rows and time to read them */ /* Approximate found rows and time to read them */
s->found_records=s->records=s->table->file->records; s->found_records=s->records=s->table->file->records;
s->read_time=(ha_rows) ((s->table->file->data_file_length)/IO_SIZE)+1; s->read_time=(ha_rows) s->table->file->scan_time();
/* Set a max range of how many seeks we can expect when using keys */ /* Set a max range of how many seeks we can expect when using keys */
s->worst_seeks= (double) (s->read_time*2); s->worst_seeks= (double) (s->read_time*2);
...@@ -1419,18 +1419,18 @@ update_ref_and_keys(DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab,uint tables, ...@@ -1419,18 +1419,18 @@ update_ref_and_keys(DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab,uint tables,
for (i=0 ; i < keyuse->elements-1 ; i++,use++) for (i=0 ; i < keyuse->elements-1 ; i++,use++)
{ {
if (!use->used_tables) if (!use->used_tables)
use->table->const_key_parts[use->key]|= use->table->const_key_parts[use->key] |=
(key_part_map) 1 << use->keypart; (key_part_map) 1 << use->keypart;
if (use->keypart != FT_KEYPART) if (use->keypart != FT_KEYPART)
{ {
if (use->key == prev->key && use->table == prev->table) if (use->key == prev->key && use->table == prev->table)
{ {
if (prev->keypart+1 < use->keypart || if (prev->keypart+1 < use->keypart ||
prev->keypart == use->keypart && found_eq_constant) prev->keypart == use->keypart && found_eq_constant)
continue; /* remove */ continue; /* remove */
} }
else if (use->keypart != 0) // First found must be 0 else if (use->keypart != 0) // First found must be 0
continue; continue;
} }
*save_pos= *use; *save_pos= *use;
...@@ -1532,7 +1532,7 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count, ...@@ -1532,7 +1532,7 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count,
double best_records=DBL_MAX; double best_records=DBL_MAX;
/* Test how we can use keys */ /* Test how we can use keys */
rec= s->records/10; /* Assume 10 records/key */ rec= s->records/MATCHING_ROWS_IN_OTHER_TABLE; /* Assumed records/key */
for (keyuse=s->keyuse ; keyuse->table == table ;) for (keyuse=s->keyuse ; keyuse->table == table ;)
{ {
key_map found_part=0; key_map found_part=0;
...@@ -1571,7 +1571,7 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count, ...@@ -1571,7 +1571,7 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count,
if (map == 1) // Only one table if (map == 1) // Only one table
{ {
TABLE *tmp_table=join->all_tables[tablenr]; TABLE *tmp_table=join->all_tables[tablenr];
if (rec > tmp_table->file->records) if (rec > tmp_table->file->records && rec > 100)
rec=max(tmp_table->file->records,100); rec=max(tmp_table->file->records,100);
} }
} }
...@@ -1615,12 +1615,12 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count, ...@@ -1615,12 +1615,12 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count,
} }
else else
{ {
if (!found_ref) // If not const key if (!found_ref)
{ { // We found a const key
if (table->quick_keys & ((key_map) 1 << key)) if (table->quick_keys & ((key_map) 1 << key))
records= (double) table->quick_rows[key]; records= (double) table->quick_rows[key];
else else
records= (double) s->records; // quick_range couldn't use key! records= (double) s->records/rec; // quick_range couldn't use key!
} }
else else
{ {
...@@ -1654,7 +1654,8 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count, ...@@ -1654,7 +1654,8 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count,
** than a not unique key ** than a not unique key
** Set tmp to (previous record count) * (records / combination) ** Set tmp to (previous record count) * (records / combination)
*/ */
if (found_part & 1) if ((found_part & 1) &&
!(table->file->option_flag() & HA_ONLY_WHOLE_INDEX))
{ {
uint max_key_part=max_part_bit(found_part); uint max_key_part=max_part_bit(found_part);
/* Check if quick_range could determinate how many rows we /* Check if quick_range could determinate how many rows we
......
...@@ -176,7 +176,7 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name, ...@@ -176,7 +176,7 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
DBUG_ENTER("mysql_create_table"); DBUG_ENTER("mysql_create_table");
/* /*
** Check for dupplicate fields and check type of table to create ** Check for duplicate fields and check type of table to create
*/ */
if (!fields.elements) if (!fields.elements)
...@@ -302,7 +302,7 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name, ...@@ -302,7 +302,7 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
bool primary_key=0,unique_key=0; bool primary_key=0,unique_key=0;
Key *key; Key *key;
uint tmp; uint tmp;
tmp=max(file->max_keys(), MAX_KEY); tmp=min(file->max_keys(), MAX_KEY);
if (key_count > tmp) if (key_count > tmp)
{ {
......
...@@ -262,6 +262,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); ...@@ -262,6 +262,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token UDF_RETURNS_SYM %token UDF_RETURNS_SYM
%token UDF_SONAME_SYM %token UDF_SONAME_SYM
%token UDF_SYM %token UDF_SYM
%token UNION_SYM
%token UNIQUE_SYM %token UNIQUE_SYM
%token USAGE %token USAGE
%token USE_SYM %token USE_SYM
...@@ -712,6 +713,18 @@ create_table_option: ...@@ -712,6 +713,18 @@ create_table_option:
| RAID_TYPE EQ raid_types { Lex->create_info.raid_type= $3; Lex->create_info.used_fields|= HA_CREATE_USED_RAID;} | RAID_TYPE EQ raid_types { Lex->create_info.raid_type= $3; Lex->create_info.used_fields|= HA_CREATE_USED_RAID;}
| RAID_CHUNKS EQ ULONG_NUM { Lex->create_info.raid_chunks= $3; Lex->create_info.used_fields|= HA_CREATE_USED_RAID;} | RAID_CHUNKS EQ ULONG_NUM { Lex->create_info.raid_chunks= $3; Lex->create_info.used_fields|= HA_CREATE_USED_RAID;}
| RAID_CHUNKSIZE EQ ULONG_NUM { Lex->create_info.raid_chunksize= $3*RAID_BLOCK_SIZE; Lex->create_info.used_fields|= HA_CREATE_USED_RAID;} | RAID_CHUNKSIZE EQ ULONG_NUM { Lex->create_info.raid_chunksize= $3*RAID_BLOCK_SIZE; Lex->create_info.used_fields|= HA_CREATE_USED_RAID;}
| UNION_SYM EQ '(' table_list ')'
{
/* Move the union list to the merge_list */
LEX *lex=Lex;
TABLE_LIST *table_list= (TABLE_LIST*) lex->table_list.first;
lex->create_info.merge_list= lex->table_list;
lex->create_info.merge_list.elements--;
lex->create_info.merge_list.first= (byte*) (table_list->next);
lex->table_list.elements=1;
lex->table_list.next= (byte**) &(table_list->next);
table_list->next=0;
}
table_types: table_types:
ISAM_SYM { $$= DB_TYPE_ISAM; } ISAM_SYM { $$= DB_TYPE_ISAM; }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment