Commit 254befa1 authored by serg@serg.mysql.com's avatar serg@serg.mysql.com

Merge

parents f8bc5e06 828bff91
monty@donna.mysql.com monty@donna.mysql.com
sasha@mysql.sashanet.com sasha@mysql.sashanet.com
serg@serg.mysql.com
...@@ -1807,6 +1807,13 @@ is as tested as the other table types. ...@@ -1807,6 +1807,13 @@ is as tested as the other table types.
This only affects the new code that checks if the table was closed properly This only affects the new code that checks if the table was closed properly
on open and executes an automatic check/repair of the table if it wasn't. on open and executes an automatic check/repair of the table if it wasn't.
@item MERGE tables -- Alpha / Beta
The usage of keys on @code{MERGE} tables is still not that tested. The
other part of the @code{MERGE} code is quite well tested.
@item FULLTEXT -- Alpha / Beta
Text search seams to work, but is still not widely used.
@end table @end table
MySQL AB provides e-mail support for paying customers, but the @strong{MySQL} MySQL AB provides e-mail support for paying customers, but the @strong{MySQL}
...@@ -9029,9 +9036,9 @@ priority in one thread. ...@@ -9029,9 +9036,9 @@ priority in one thread.
@item --memlock @item --memlock
Lock the @code{mysqld} process in memory. This works only if your system Lock the @code{mysqld} process in memory. This works only if your system
supports the @code{mlockall()} system call. This may help if you have supports the @code{mlockall()} system call. This may help if you have
a problem where the opearting system is causing @code{mysqld} to swap on disk. a problem where the operating system is causing @code{mysqld} to swap on disk.
@item --myisam-recover [=option[,option...]]] where option is one of DEFAULT, BACKUP or FORCE. @item --myisam-recover [=option[,option...]]] where option is one of DEFAULT, BACKUP, FORCE or QUICK.
If this option is used, @code{mysqld} will on open check if the table is If this option is used, @code{mysqld} will on open check if the table is
marked as crashed or if if the table wasn't closed properly marked as crashed or if if the table wasn't closed properly
(The last option only works if you are running with @code{--skip-locking}). (The last option only works if you are running with @code{--skip-locking}).
...@@ -9044,10 +9051,15 @@ The following options affects how the repair works. ...@@ -9044,10 +9051,15 @@ The following options affects how the repair works.
@item DEFAULT @tab The same as not giving any option to @code{--myisam-recover}. @item DEFAULT @tab The same as not giving any option to @code{--myisam-recover}.
@item BACKUP @tab If the data table was changed during recover, save a backup of the @file{table_name.MYD} data file as @file{table_name-datetime.BAK}. @item BACKUP @tab If the data table was changed during recover, save a backup of the @file{table_name.MYD} data file as @file{table_name-datetime.BAK}.
@item FORCE @tab Run recover even if we will loose more than one row from the .MYD file. @item FORCE @tab Run recover even if we will loose more than one row from the .MYD file.
@item QUICK @tab Don't check the rows in the table if there isn't any delete blocks.
@end multitable @end multitable
Before a table is automaticly repaired, mysqld will add a note about this Before a table is automaticly repaired, mysqld will add a note about
in the error log. this in the error log. If you want to be able to recover from most
things without user intervention, you should use the options
@code{BACKUP,FORCE}. This will force a repair of a table even if some rows
would be deleted, but it will keep the old data file as a backup so that
you can later examine what happened.
@item --pid-file=path @item --pid-file=path
Path to pid file used by @code{safe_mysqld}. Path to pid file used by @code{safe_mysqld}.
...@@ -16312,7 +16324,8 @@ Version 3.22. @code{ADDDATE()} and @code{SUBDATE()} are synonyms for ...@@ -16312,7 +16324,8 @@ Version 3.22. @code{ADDDATE()} and @code{SUBDATE()} are synonyms for
@code{DATE_ADD()} and @code{DATE_SUB()}. @code{DATE_ADD()} and @code{DATE_SUB()}.
In @strong{MySQL} Version 3.23, you can use @code{+} and @code{-} instead of In @strong{MySQL} Version 3.23, you can use @code{+} and @code{-} instead of
@code{DATE_ADD()} and @code{DATE_SUB()}. (See example) @code{DATE_ADD()} and @code{DATE_SUB()} if the expression on the right side is
a date or datetime column. (See example)
@code{date} is a @code{DATETIME} or @code{DATE} value specifying the starting @code{date} is a @code{DATETIME} or @code{DATE} value specifying the starting
date. @code{expr} is an expression specifying the interval value to be added date. @code{expr} is an expression specifying the interval value to be added
...@@ -20214,7 +20227,9 @@ this join type is good. ...@@ -20214,7 +20227,9 @@ this join type is good.
@item range @item range
Only rows that are in a given range will be retrieved, using an index to Only rows that are in a given range will be retrieved, using an index to
select the rows. The @code{ref} column indicates which index is used. select the rows. The @code{key} column indicates which index is used.
The @code{key_len} contains the longest key part that was used.
The @code{ref} column will be NULL for this type.
@item index @item index
This is the same as @code{ALL}, except that only the index tree is This is the same as @code{ALL}, except that only the index tree is
...@@ -21256,7 +21271,7 @@ of both worlds. ...@@ -21256,7 +21271,7 @@ of both worlds.
@menu @menu
* MyISAM:: MyISAM tables * MyISAM:: MyISAM tables
* MERGE:: * MERGE:: MERGE tables
* ISAM:: ISAM tables * ISAM:: ISAM tables
* HEAP:: HEAP tables * HEAP:: HEAP tables
* BDB:: BDB or Berkeley_db tables * BDB:: BDB or Berkeley_db tables
...@@ -21368,11 +21383,37 @@ The following options to @code{mysqld} can be used to change the behavior of ...@@ -21368,11 +21383,37 @@ The following options to @code{mysqld} can be used to change the behavior of
@multitable @columnfractions .40 .60 @multitable @columnfractions .40 .60
@item @strong{Option} @tab @strong{Meaning} @item @strong{Option} @tab @strong{Meaning}
@item @code{--myisam-recover} @tab Automatic recover of crashed tables. @item @code{--myisam-recover=#} @tab Automatic recover of crashed tables.
@item @code{-O myisam_sort_buffer_size=#} @tab Buffer used when recovering tables. @item @code{-O myisam_sort_buffer_size=#} @tab Buffer used when recovering tables.
@item @code{--delay-key-write-for-all-tables} @tab Don't flush key buffers between writes for any MyISAM table @item @code{--delay-key-write-for-all-tables} @tab Don't flush key buffers between writes for any MyISAM table
@end multitable @end multitable
The automatic recovery is activated if you start mysqld with
@code{--myisam-recover=#}. @xref{Command-line options}.
On open, the table is checked if it's marked as crashed or if the open
count variable for the table is not 0 and you are running with
@code{--skip-locking}. If either of the above is true the following happens.
@itemize @bullet
@item
The table is checked for errors.
@item
If we found an error, try to do a fast repair (with sorting and without
recreating the data file) of the table.
@item
If the repair fails because of an error in the data file (for example a
duplicate key error), we try again, but this time we recreate the data file.
@item
If the repair fails, retry once more with the old repair option method
(write row by row without sorting) which should be able to repair any
type of error with little disk requirements..
@end itemize
Note that if you run automatic recover with the @code{BACKUP} option,
you should have a cron script that automaticly moves file with names
like @file{tablename-datetime.BAK} from the database directories to a
backup media.
@xref{Command-line options}. @xref{Command-line options}.
@menu @menu
...@@ -21903,6 +21944,9 @@ properly locked if one another thread issues a table lock. ...@@ -21903,6 +21944,9 @@ properly locked if one another thread issues a table lock.
@item @item
Internal locking in @code{BDB} tables are done on page level. Internal locking in @code{BDB} tables are done on page level.
@item @item
@code{SELECT COUNT(*) FROM table_name} is slow as @code{BDB} tables doesn't
maintain a count of the number of rows in the table.
@item
Scanning is slower than with @code{MyISAM} tables as one has data in BDB Scanning is slower than with @code{MyISAM} tables as one has data in BDB
tables is stored in B-trees and not in a separate data file. tables is stored in B-trees and not in a separate data file.
@item @item
...@@ -37037,7 +37081,7 @@ This listing. ...@@ -37037,7 +37081,7 @@ This listing.
Perl @code{Data-Dumper} module. Useful with @code{DBI}/@code{DBD} support for Perl @code{Data-Dumper} module. Useful with @code{DBI}/@code{DBD} support for
older perl installations. older perl installations.
@item @uref{http://www.mysql.com/Downloads/Contrib/DBI-1.13.tar.gz, DBI-1.13.tar.gz} @item @uref{http://www.mysql.com/Downloads/Contrib/DBI-1.14.tar.gz, DBI-1.14.tar.gz}
Perl @code{DBI} module. Perl @code{DBI} module.
@item @uref{http://www.mysql.com/Downloads/Contrib/KAMXbase1.0.tar.gz,KAMXbase1.0.tar.gz} @item @uref{http://www.mysql.com/Downloads/Contrib/KAMXbase1.0.tar.gz,KAMXbase1.0.tar.gz}
...@@ -37046,7 +37090,7 @@ module written by Pratap Pereira @email{pereira@@ee.eng.ohio-state.edu}, ...@@ -37046,7 +37090,7 @@ module written by Pratap Pereira @email{pereira@@ee.eng.ohio-state.edu},
extened by Kevin A. McGrail @email{kmcgrail@@digital1.peregrinehw.com}. extened by Kevin A. McGrail @email{kmcgrail@@digital1.peregrinehw.com}.
This converter can handle MEMO fields. This converter can handle MEMO fields.
@item @uref{http://www.mysql.com/Downloads/Contrib/Msql-Mysql-modules-1.2214.tar.gz, Msql-Mysql-modules-1.2214.tar.gz} @item @uref{http://www.mysql.com/Downloads/Contrib/Msql-Mysql-modules-1.2215.tar.gz, Msql-Mysql-modules-1.2215.tar.gz}
Perl @code{DBD} module to access mSQL and @strong{MySQL} databases.. Perl @code{DBD} module to access mSQL and @strong{MySQL} databases..
@item @uref{http://www.mysql.com/Downloads/Contrib/Data-ShowTable-3.3.tar.gz, Data-ShowTable-3.3.tar.gz} @item @uref{http://www.mysql.com/Downloads/Contrib/Data-ShowTable-3.3.tar.gz, Data-ShowTable-3.3.tar.gz}
...@@ -38003,6 +38047,12 @@ though, so 3.23 is not released as a stable version yet. ...@@ -38003,6 +38047,12 @@ though, so 3.23 is not released as a stable version yet.
@appendixsubsec Changes in release 3.23.26 @appendixsubsec Changes in release 3.23.26
@itemize @bullet @itemize @bullet
@item @item
Fixed problem with @code{SUBSTRING_INDEX()} and @code{REPLACE()}.
(Patch by Alexander Igonitchev)
@item
@code{CREATE TEMPORARY TABLE IF NOT EXISTS} doesn't anymore give an error
if the table existed.
@item
If one don't create a @code{PRIMARY KEY} in a BDB table, a hidden If one don't create a @code{PRIMARY KEY} in a BDB table, a hidden
@code{PRIMARY KEY} will be created. @code{PRIMARY KEY} will be created.
@item @item
...@@ -30,16 +30,14 @@ noinst_HEADERS = global.h config-win.h \ ...@@ -30,16 +30,14 @@ noinst_HEADERS = global.h config-win.h \
my_tree.h hash.h thr_alarm.h thr_lock.h \ my_tree.h hash.h thr_alarm.h thr_lock.h \
getopt.h t_ctype.h violite.h \ getopt.h t_ctype.h violite.h \
mysql_version.h.in mysql_version.h.in
EXTRA_DIST= my_config.h
# mysql_version.h are generated # mysql_version.h are generated
SUPERCLEANFILES = mysql_version.h my_global.h SUPERCLEANFILES = mysql_version.h my_global.h my_config.h
# Some include files that may be moved and patched by configure # Some include files that may be moved and patched by configure
DISTCLEANFILES = sched.h DISTCLEANFILES = sched.h
CLEANFILES = my_config.h
all-local: my_global.h all-local: my_global.h my_config.h
# Since we include my_config.h it better exist from the beginning # Since we include my_config.h it better exist from the beginning
link_sources: link_sources:
......
...@@ -57,8 +57,8 @@ struct timespec { /* For pthread_cond_timedwait() */ ...@@ -57,8 +57,8 @@ struct timespec { /* For pthread_cond_timedwait() */
typedef int pthread_mutexattr_t; typedef int pthread_mutexattr_t;
#define win_pthread_self my_thread_var->pthread_self #define win_pthread_self my_thread_var->pthread_self
#define pthread_handler_decl(A,B) unsigned __cdecl A(void *B) #define pthread_handler_decl(A,B) void * __cdecl A(void *B)
typedef unsigned (__cdecl *pthread_handler)(void *); typedef void * (__cdecl *pthread_handler)(void *);
void win_pthread_init(void); void win_pthread_init(void);
int win_pthread_setspecific(void *A,void *B,uint length); int win_pthread_setspecific(void *A,void *B,uint length);
......
...@@ -504,7 +504,8 @@ static int chk_index(MI_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo, ...@@ -504,7 +504,8 @@ static int chk_index(MI_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo,
if (used_length > keyinfo->block_length) if (used_length > keyinfo->block_length)
{ {
mi_check_print_error(param,"Wrong pageinfo at page: %s", llstr(page,llbuff)); mi_check_print_error(param,"Wrong pageinfo at page: %s",
llstr(page,llbuff));
goto err; goto err;
} }
for ( ;; ) for ( ;; )
...@@ -1172,9 +1173,9 @@ int mi_repair(MI_CHECK *param, register MI_INFO *info, ...@@ -1172,9 +1173,9 @@ int mi_repair(MI_CHECK *param, register MI_INFO *info,
if (my_errno != HA_ERR_FOUND_DUPP_KEY) goto err; if (my_errno != HA_ERR_FOUND_DUPP_KEY) goto err;
DBUG_DUMP("record",(byte*) sort_info->record,share->base.pack_reclength); DBUG_DUMP("record",(byte*) sort_info->record,share->base.pack_reclength);
mi_check_print_info(param,"Duplicate key %2d for record at %10s against new record at %10s", mi_check_print_info(param,"Duplicate key %2d for record at %10s against new record at %10s",
info->errkey+1, info->errkey+1,
llstr(sort_info->start_recpos,llbuff), llstr(sort_info->start_recpos,llbuff),
llstr(info->lastpos,llbuff2)); llstr(info->dupp_key_pos,llbuff2));
if (param->testflag & T_VERBOSE) if (param->testflag & T_VERBOSE)
{ {
VOID(_mi_make_key(info,(uint) info->errkey,info->lastkey, VOID(_mi_make_key(info,(uint) info->errkey,info->lastkey,
...@@ -1185,7 +1186,7 @@ int mi_repair(MI_CHECK *param, register MI_INFO *info, ...@@ -1185,7 +1186,7 @@ int mi_repair(MI_CHECK *param, register MI_INFO *info,
sort_info->dupp++; sort_info->dupp++;
if (rep_quick == 1) if (rep_quick == 1)
{ {
param->error_printed=1; param->error_printed=param->retry_without_quick=1;
goto err; goto err;
} }
continue; continue;
...@@ -1217,6 +1218,16 @@ int mi_repair(MI_CHECK *param, register MI_INFO *info, ...@@ -1217,6 +1218,16 @@ int mi_repair(MI_CHECK *param, register MI_INFO *info,
param->retry_repair=param->retry_without_quick=1; param->retry_repair=param->retry_without_quick=1;
goto err; goto err;
} }
if (param->testflag & T_SAFE_REPAIR)
{
/* Don't repair if we loosed more than one row */
if (info->state->records+1 < start_records)
{
info->state->records=start_records;
got_error=1;
goto err;
}
}
if (!rep_quick) if (!rep_quick)
{ {
...@@ -1225,7 +1236,6 @@ int mi_repair(MI_CHECK *param, register MI_INFO *info, ...@@ -1225,7 +1236,6 @@ int mi_repair(MI_CHECK *param, register MI_INFO *info,
info->state->data_file_length=sort_info->filepos; info->state->data_file_length=sort_info->filepos;
/* Only whole records */ /* Only whole records */
share->state.split=info->state->records+info->state->del; share->state.split=info->state->records+info->state->del;
param->out_flag|=O_NEW_DATA; /* Data in new file */
share->state.version=(ulong) time((time_t*) 0); /* Force reopen */ share->state.version=(ulong) time((time_t*) 0); /* Force reopen */
} }
else else
...@@ -1247,6 +1257,21 @@ int mi_repair(MI_CHECK *param, register MI_INFO *info, ...@@ -1247,6 +1257,21 @@ int mi_repair(MI_CHECK *param, register MI_INFO *info,
memcpy( &share->state.state, info->state, sizeof(*info->state)); memcpy( &share->state.state, info->state, sizeof(*info->state));
err: err:
if (!got_error)
{
/* Replace the actual file with the temporary file */
if (new_file >= 0)
{
my_close(new_file,MYF(0));
info->dfile=new_file= -1;
if (change_to_newfile(share->filename,MI_NAME_DEXT,
DATA_TMP_EXT, share->base.raid_chunks,
(param->testflag & T_BACKUP_DATA ?
MYF(MY_REDEL_MAKE_BACKUP): MYF(0))) ||
mi_open_datafile(info,share))
got_error=1;
}
}
if (got_error) if (got_error)
{ {
if (! param->error_printed) if (! param->error_printed)
...@@ -1274,7 +1299,8 @@ err: ...@@ -1274,7 +1299,8 @@ err:
share->pack.header_length=0; share->pack.header_length=0;
share->data_file_type=sort_info->new_data_file_type; share->data_file_type=sort_info->new_data_file_type;
} }
share->state.changed|=STATE_NOT_OPTIMIZED_KEYS | STATE_NOT_SORTED_PAGES; share->state.changed|= (STATE_NOT_OPTIMIZED_KEYS | STATE_NOT_SORTED_PAGES |
STATE_NOT_ANALYZED);
DBUG_RETURN(got_error); DBUG_RETURN(got_error);
} }
...@@ -1453,14 +1479,17 @@ int mi_sort_index(MI_CHECK *param, register MI_INFO *info, my_string name) ...@@ -1453,14 +1479,17 @@ int mi_sort_index(MI_CHECK *param, register MI_INFO *info, my_string name)
flush_key_blocks(info->s->kfile, FLUSH_IGNORE_CHANGED); flush_key_blocks(info->s->kfile, FLUSH_IGNORE_CHANGED);
/* Put same locks as old file */ /* Put same locks as old file */
if (lock_file(param,new_file,0L,F_WRLCK,"tempfile",param->temp_filename))
goto err;
info->s->state.version=(ulong) time((time_t*) 0); info->s->state.version=(ulong) time((time_t*) 0);
VOID(_mi_writeinfo(info,WRITEINFO_UPDATE_KEYFILE)); VOID(_mi_writeinfo(info,WRITEINFO_UPDATE_KEYFILE));
VOID(my_close(info->s->kfile,MYF(MY_WME))); VOID(my_close(info->s->kfile,MYF(MY_WME)));
param->out_flag|=O_NEW_INDEX; /* Data in new file */ info->s->kfile = -1;
VOID(my_close(new_file,MYF(MY_WME)));
if (change_to_newfile(info->s->filename,MI_NAME_IEXT,INDEX_TMP_EXT,0,
MYF(0)) ||
mi_open_keyfile(info->s))
goto err2;
_mi_readinfo(info,F_WRLCK,0);
info->s->kfile=new_file;
info->state->key_file_length=param->new_file_pos; info->state->key_file_length=param->new_file_pos;
info->update= (short) (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED); info->update= (short) (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
for (key=0 ; key < info->s->base.keys ; key++) for (key=0 ; key < info->s->base.keys ; key++)
...@@ -1473,6 +1502,7 @@ int mi_sort_index(MI_CHECK *param, register MI_INFO *info, my_string name) ...@@ -1473,6 +1502,7 @@ int mi_sort_index(MI_CHECK *param, register MI_INFO *info, my_string name)
err: err:
VOID(my_close(new_file,MYF(MY_WME))); VOID(my_close(new_file,MYF(MY_WME)));
err2:
VOID(my_delete(param->temp_filename,MYF(MY_WME))); VOID(my_delete(param->temp_filename,MYF(MY_WME)));
DBUG_RETURN(-1); DBUG_RETURN(-1);
} /* sort_index */ } /* sort_index */
...@@ -1842,7 +1872,6 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info, ...@@ -1842,7 +1872,6 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info,
/* Only whole records */ /* Only whole records */
share->state.split=info->state->records+info->state->del; share->state.split=info->state->records+info->state->del;
share->state.version=(ulong) time((time_t*) 0); share->state.version=(ulong) time((time_t*) 0);
param->out_flag|=O_NEW_DATA; /* Data in new file */
my_close(info->dfile,MYF(0)); my_close(info->dfile,MYF(0));
info->dfile=new_file; info->dfile=new_file;
share->data_file_type=sort_info->new_data_file_type; share->data_file_type=sort_info->new_data_file_type;
...@@ -1909,18 +1938,34 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info, ...@@ -1909,18 +1938,34 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info,
memcpy( &share->state.state, info->state, sizeof(*info->state)); memcpy( &share->state.state, info->state, sizeof(*info->state));
err: err:
got_error|= flush_blocks(param,share->kfile);
VOID(end_io_cache(&info->rec_cache));
if (!got_error)
{
/* Replace the actual file with the temporary file */
if (new_file >= 0)
{
my_close(new_file,MYF(0));
info->dfile=new_file= -1;
if (change_to_newfile(share->filename,MI_NAME_DEXT,
DATA_TMP_EXT, share->base.raid_chunks,
(param->testflag & T_BACKUP_DATA ?
MYF(MY_REDEL_MAKE_BACKUP): MYF(0))) ||
mi_open_datafile(info,share))
got_error=1;
}
}
if (got_error) if (got_error)
{ {
if (! param->error_printed) if (! param->error_printed)
mi_check_print_error(param,"%d when fixing table",my_errno); mi_check_print_error(param,"%d when fixing table",my_errno);
if (new_file >= 0) if (new_file >= 0)
{ {
VOID(end_io_cache(&info->rec_cache));
VOID(my_close(new_file,MYF(0))); VOID(my_close(new_file,MYF(0)));
VOID(my_raid_delete(param->temp_filename,info->s->base.raid_chunks, VOID(my_raid_delete(param->temp_filename,share->base.raid_chunks,
MYF(MY_WME))); MYF(MY_WME)));
if (info->dfile == new_file) if (info->dfile == new_file)
info->dfile=0; info->dfile= -1;
} }
mi_mark_crashed_on_repair(info); mi_mark_crashed_on_repair(info);
} }
...@@ -1932,7 +1977,6 @@ err: ...@@ -1932,7 +1977,6 @@ err:
my_free(sort_info->record,MYF(MY_ALLOW_ZERO_PTR)); my_free(sort_info->record,MYF(MY_ALLOW_ZERO_PTR));
my_free(sort_info->buff,MYF(MY_ALLOW_ZERO_PTR)); my_free(sort_info->buff,MYF(MY_ALLOW_ZERO_PTR));
VOID(end_io_cache(&param->read_cache)); VOID(end_io_cache(&param->read_cache));
VOID(end_io_cache(&info->rec_cache));
info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED); info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
if (!got_error && (param->testflag & T_UNPACK)) if (!got_error && (param->testflag & T_UNPACK))
{ {
...@@ -2350,8 +2394,8 @@ int sort_write_record(SORT_INFO *sort_info) ...@@ -2350,8 +2394,8 @@ int sort_write_record(SORT_INFO *sort_info)
if (sort_info->buff_length < reclength) if (sort_info->buff_length < reclength)
{ {
if (!(sort_info->buff=my_realloc(sort_info->buff, (uint) reclength, if (!(sort_info->buff=my_realloc(sort_info->buff, (uint) reclength,
MYF(MY_FREE_ON_ERROR | MYF(MY_FREE_ON_ERROR |
MY_ALLOW_ZERO_PTR)))) MY_ALLOW_ZERO_PTR))))
DBUG_RETURN(1); DBUG_RETURN(1);
sort_info->buff_length=reclength; sort_info->buff_length=reclength;
} }
...@@ -2440,6 +2484,7 @@ static int sort_key_write(SORT_INFO *sort_info, const void *a) ...@@ -2440,6 +2484,7 @@ static int sort_key_write(SORT_INFO *sort_info, const void *a)
sort_info->key_block-> sort_info->key_block->
lastkey), lastkey),
llbuff2)); llbuff2));
param->error_printed=param->retry_without_quick=1;
if (sort_info->param->testflag & T_VERBOSE) if (sort_info->param->testflag & T_VERBOSE)
_mi_print_key(stdout,sort_info->keyseg,(uchar*) a, USE_WHOLE_KEY); _mi_print_key(stdout,sort_info->keyseg,(uchar*) a, USE_WHOLE_KEY);
return (sort_delete_record(param)); return (sort_delete_record(param));
...@@ -2474,7 +2519,7 @@ static int sort_insert_key(MI_CHECK *param, ...@@ -2474,7 +2519,7 @@ static int sort_insert_key(MI_CHECK *param,
my_off_t prev_block) my_off_t prev_block)
{ {
uint a_length,t_length,nod_flag; uint a_length,t_length,nod_flag;
my_off_t filepos; my_off_t filepos,key_file_length;
uchar *anc_buff,*lastkey; uchar *anc_buff,*lastkey;
MI_KEY_PARAM s_temp; MI_KEY_PARAM s_temp;
MI_INFO *info; MI_INFO *info;
...@@ -2525,11 +2570,20 @@ static int sort_insert_key(MI_CHECK *param, ...@@ -2525,11 +2570,20 @@ static int sort_insert_key(MI_CHECK *param,
mi_putint(anc_buff,key_block->last_length,nod_flag); mi_putint(anc_buff,key_block->last_length,nod_flag);
bzero((byte*) anc_buff+key_block->last_length, bzero((byte*) anc_buff+key_block->last_length,
sort_info->keyinfo->block_length- key_block->last_length); sort_info->keyinfo->block_length- key_block->last_length);
key_file_length=info->state->key_file_length;
if ((filepos=_mi_new(info,sort_info->keyinfo)) == HA_OFFSET_ERROR) if ((filepos=_mi_new(info,sort_info->keyinfo)) == HA_OFFSET_ERROR)
return 1; DBUG_RETURN(1);
if (my_pwrite(info->s->kfile,(byte*) anc_buff,
(uint) sort_info->keyinfo->block_length,filepos, /* If we read the page from the key cache, we have to write it back to it */
param->myf_rw)) if (key_file_length == info->state->key_file_length)
{
if (_mi_write_keypage(info, sort_info->keyinfo, filepos,
anc_buff))
DBUG_RETURN(1);
}
else if (my_pwrite(info->s->kfile,(byte*) anc_buff,
(uint) sort_info->keyinfo->block_length,filepos,
param->myf_rw))
DBUG_RETURN(1); DBUG_RETURN(1);
DBUG_DUMP("buff",(byte*) anc_buff,mi_getint(anc_buff)); DBUG_DUMP("buff",(byte*) anc_buff,mi_getint(anc_buff));
...@@ -2607,7 +2661,7 @@ static int sort_delete_record(MI_CHECK *param) ...@@ -2607,7 +2661,7 @@ static int sort_delete_record(MI_CHECK *param)
static int flush_pending_blocks(MI_CHECK *param) static int flush_pending_blocks(MI_CHECK *param)
{ {
uint nod_flag,length; uint nod_flag,length;
my_off_t filepos; my_off_t filepos,key_file_length;
MI_INFO *info; MI_INFO *info;
SORT_KEY_BLOCKS *key_block; SORT_KEY_BLOCKS *key_block;
SORT_INFO *sort_info= &param->sort_info; SORT_INFO *sort_info= &param->sort_info;
...@@ -2622,18 +2676,27 @@ static int flush_pending_blocks(MI_CHECK *param) ...@@ -2622,18 +2676,27 @@ static int flush_pending_blocks(MI_CHECK *param)
length=mi_getint(key_block->buff); length=mi_getint(key_block->buff);
if (nod_flag) if (nod_flag)
_mi_kpointer(info,key_block->end_pos,filepos); _mi_kpointer(info,key_block->end_pos,filepos);
if ((filepos=_mi_new(info,sort_info->keyinfo)) == HA_OFFSET_ERROR) key_file_length=info->state->key_file_length;
DBUG_RETURN(1);
bzero((byte*) key_block->buff+length, bzero((byte*) key_block->buff+length,
sort_info->keyinfo->block_length-length); sort_info->keyinfo->block_length-length);
if (my_pwrite(info->s->kfile,(byte*) key_block->buff, if ((filepos=_mi_new(info,sort_info->keyinfo)) == HA_OFFSET_ERROR)
(uint) sort_info->keyinfo->block_length,filepos, DBUG_RETURN(1);
param->myf_rw))
/* If we read the page from the key cache, we have to write it back */
if (key_file_length == info->state->key_file_length)
{
if (_mi_write_keypage(info, sort_info->keyinfo, filepos,
key_block->buff))
DBUG_RETURN(1);
}
else if (my_pwrite(info->s->kfile,(byte*) key_block->buff,
(uint) sort_info->keyinfo->block_length,filepos,
param->myf_rw))
DBUG_RETURN(1); DBUG_RETURN(1);
DBUG_DUMP("buff",(byte*) key_block->buff,length); DBUG_DUMP("buff",(byte*) key_block->buff,length);
nod_flag=1; nod_flag=1;
} }
info->s->state.key_root[sort_info->key]=filepos; /* Last is root for tree */ info->s->state.key_root[sort_info->key]=filepos; /* Last is root for tree */
DBUG_RETURN(0); DBUG_RETURN(0);
} /* flush_pending_blocks */ } /* flush_pending_blocks */
......
...@@ -101,6 +101,7 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags) ...@@ -101,6 +101,7 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
(kfile=my_open(name_buff,(open_mode=O_RDONLY) | O_SHARE,MYF(0))) < 0) (kfile=my_open(name_buff,(open_mode=O_RDONLY) | O_SHARE,MYF(0))) < 0)
goto err; goto err;
} }
share->mode=open_mode;
errpos=1; errpos=1;
if (my_read(kfile,(char*) share->state.header.file_version,head_length, if (my_read(kfile,(char*) share->state.header.file_version,head_length,
MYF(MY_NABP))) MYF(MY_NABP)))
...@@ -343,28 +344,11 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags) ...@@ -343,28 +344,11 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
lock_error=1; /* Database unlocked */ lock_error=1; /* Database unlocked */
} }
#ifdef USE_RAID if (mi_open_datafile(&info, share))
if (share->base.raid_type)
{
if ((info.dfile=my_raid_open(fn_format(name_buff,name,"",MI_NAME_DEXT,
2+4),
mode | O_SHARE,
share->base.raid_type,
share->base.raid_chunks,
share->base.raid_chunksize,
MYF(MY_WME | MY_RAID))) < 0)
goto err; goto err;
}
else
#endif
if ((info.dfile=my_open(fn_format(name_buff,name,"",MI_NAME_DEXT,2+4),
mode | O_SHARE,
MYF(MY_WME))) < 0)
goto err;
errpos=5; errpos=5;
share->kfile=kfile; share->kfile=kfile;
share->mode=open_mode;
share->this_process=(ulong) getpid(); share->this_process=(ulong) getpid();
share->rnd= (int) share->this_process; /* rnd-counter for splits */ share->rnd= (int) share->this_process; /* rnd-counter for splits */
#ifndef DBUG_OFF #ifndef DBUG_OFF
...@@ -433,27 +417,8 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags) ...@@ -433,27 +417,8 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
my_errno=EACCES; /* Can't open in write mode */ my_errno=EACCES; /* Can't open in write mode */
goto err; goto err;
} }
#ifdef USE_RAID if (mi_open_datafile(&info, share))
if (share->base.raid_type)
{
if ((info.dfile=my_raid_open(fn_format(name_buff,old_info->filename,"",
MI_NAME_DEXT, 2+4),
mode | O_SHARE,
share->base.raid_type,
share->base.raid_chunks,
share->base.raid_chunksize,
MYF(MY_WME | MY_RAID))) < 0)
goto err; goto err;
}
else
#endif
if ((info.dfile=my_open(fn_format(name_buff,old_info->filename,"",
MI_NAME_DEXT,2+4),
mode | O_SHARE,MYF(MY_WME))) < 0)
{
my_errno=errno;
goto err;
}
errpos=5; errpos=5;
} }
...@@ -1009,3 +974,40 @@ char *mi_recinfo_read(char *ptr, MI_COLUMNDEF *recinfo) ...@@ -1009,3 +974,40 @@ char *mi_recinfo_read(char *ptr, MI_COLUMNDEF *recinfo)
recinfo->null_pos=mi_uint2korr(ptr); ptr +=2; recinfo->null_pos=mi_uint2korr(ptr); ptr +=2;
return ptr; return ptr;
} }
/**************************************************************************
** Help functions for recover
*************************************************************************/
int mi_open_datafile(MI_INFO *info, MYISAM_SHARE *share)
{
char name_buff[FN_REFLEN];
(void) fn_format(name_buff, share->filename,"",MI_NAME_DEXT, 2+4);
#ifdef USE_RAID
if (share->base.raid_type)
{
if ((info->dfile=my_raid_open(name_buff,
share->mode | O_SHARE,
share->base.raid_type,
share->base.raid_chunks,
share->base.raid_chunksize,
MYF(MY_WME | MY_RAID))) < 0)
return 1;
}
else
#endif
if ((info->dfile=my_open(name_buff, share->mode | O_SHARE,
MYF(MY_WME))) < 0)
return 1;
return 0;
}
int mi_open_keyfile(MYISAM_SHARE *share)
{
if ((share->kfile=my_open(share->filename, share->mode | O_SHARE,
MYF(MY_WME))) < 0)
return 1;
return 0;
}
...@@ -99,6 +99,7 @@ int _mi_dispose(register MI_INFO *info, MI_KEYDEF *keyinfo, my_off_t pos) ...@@ -99,6 +99,7 @@ int _mi_dispose(register MI_INFO *info, MI_KEYDEF *keyinfo, my_off_t pos)
my_off_t old_link; my_off_t old_link;
char buff[8]; char buff[8];
DBUG_ENTER("_mi_dispose"); DBUG_ENTER("_mi_dispose");
DBUG_PRINT("enter",("pos: %ld", (long) pos));
old_link=info->s->state.key_del[keyinfo->block_size]; old_link=info->s->state.key_del[keyinfo->block_size];
info->s->state.key_del[keyinfo->block_size]=pos; info->s->state.key_del[keyinfo->block_size]=pos;
...@@ -141,6 +142,6 @@ my_off_t _mi_new(register MI_INFO *info, MI_KEYDEF *keyinfo) ...@@ -141,6 +142,6 @@ my_off_t _mi_new(register MI_INFO *info, MI_KEYDEF *keyinfo)
info->s->state.key_del[keyinfo->block_size]=mi_sizekorr(buff); info->s->state.key_del[keyinfo->block_size]=mi_sizekorr(buff);
} }
info->s->state.changed|= STATE_NOT_SORTED_PAGES; info->s->state.changed|= STATE_NOT_SORTED_PAGES;
DBUG_PRINT("exit",("Pos: %d",pos)); DBUG_PRINT("exit",("Pos: %ld",(long) pos));
DBUG_RETURN(pos); DBUG_RETURN(pos);
} /* _mi_new */ } /* _mi_new */
...@@ -196,7 +196,7 @@ static struct option long_options[] = ...@@ -196,7 +196,7 @@ static struct option long_options[] =
static void print_version(void) static void print_version(void)
{ {
printf("%s Ver 1.34 for %s at %s\n",my_progname,SYSTEM_TYPE, printf("%s Ver 1.35 for %s at %s\n",my_progname,SYSTEM_TYPE,
MACHINE_TYPE); MACHINE_TYPE);
} }
...@@ -481,6 +481,7 @@ static int myisamchk(MI_CHECK *param, my_string filename) ...@@ -481,6 +481,7 @@ static int myisamchk(MI_CHECK *param, my_string filename)
File datafile; File datafile;
char fixed_name[FN_REFLEN]; char fixed_name[FN_REFLEN];
char llbuff[22],llbuff2[22]; char llbuff[22],llbuff2[22];
my_bool state_updated=0;
MYISAM_SHARE *share; MYISAM_SHARE *share;
DBUG_ENTER("myisamchk"); DBUG_ENTER("myisamchk");
...@@ -665,43 +666,32 @@ static int myisamchk(MI_CHECK *param, my_string filename) ...@@ -665,43 +666,32 @@ static int myisamchk(MI_CHECK *param, my_string filename)
(share->state.key_map || (share->state.key_map ||
(rep_quick && !param->keys_in_use && !recreate)) && (rep_quick && !param->keys_in_use && !recreate)) &&
mi_test_if_sort_rep(info, info->state->records, 1)) mi_test_if_sort_rep(info, info->state->records, 1))
{
error=mi_repair_by_sort(&check_param,info,fixed_name,rep_quick); error=mi_repair_by_sort(&check_param,info,fixed_name,rep_quick);
state_updated=1;
}
else if (param->testflag & (T_REP | T_REP_BY_SORT)) else if (param->testflag & (T_REP | T_REP_BY_SORT))
error=mi_repair(&check_param, info,fixed_name,rep_quick); error=mi_repair(&check_param, info,fixed_name,rep_quick);
} }
if (!error && param->testflag & T_SORT_RECORDS) if (!error && param->testflag & T_SORT_RECORDS)
{ {
/*
The data file is nowadays reopened in the repair code so we should
soon remove the following reopen-code
*/
#ifndef TO_BE_REMOVED
if (param->out_flag & O_NEW_DATA) if (param->out_flag & O_NEW_DATA)
{ /* Change temp file to org file */ { /* Change temp file to org file */
VOID(my_close(info->dfile,MYF(MY_WME))); /* Close new file */ VOID(my_close(info->dfile,MYF(MY_WME))); /* Close new file */
error|=change_to_newfile(fixed_name,MI_NAME_DEXT,DATA_TMP_EXT, error|=change_to_newfile(fixed_name,MI_NAME_DEXT,DATA_TMP_EXT,
raid_chunks, raid_chunks,
MYF(0)); MYF(0));
#ifdef USE_RAID if (mi_open_datafile(info,info->s))
if (share->base.raid_type)
{
mi_check_print_info(&check_param,"Opening as RAID-ed table\n");
info->dfile=my_raid_open(fn_format(param->temp_filename,
fixed_name,"",
MI_NAME_DEXT, 2+4),
O_RDWR | O_SHARE,
share->base.raid_type,
raid_chunks,
share->base.raid_chunksize,
MYF(MY_WME | MY_RAID));
}
else
#endif
info->dfile=my_open(fn_format(param->temp_filename,
fixed_name,"",
MI_NAME_DEXT,2+4),
O_RDWR | O_SHARE,
MYF(MY_WME));
if (info->dfile < 0)
error=1; error=1;
param->out_flag&= ~O_NEW_DATA; /* We are using new datafile */ param->out_flag&= ~O_NEW_DATA; /* We are using new datafile */
param->read_cache.file=info->dfile; param->read_cache.file=info->dfile;
} }
#endif
if (! error) if (! error)
{ {
uint key; uint key;
...@@ -757,7 +747,11 @@ static int myisamchk(MI_CHECK *param, my_string filename) ...@@ -757,7 +747,11 @@ static int myisamchk(MI_CHECK *param, my_string filename)
{ {
error|=chk_key(param, info); error|=chk_key(param, info);
if (!error && (param->testflag & (T_STATISTICS | T_AUTO_INC))) if (!error && (param->testflag & (T_STATISTICS | T_AUTO_INC)))
error=update_state_info(param, info, UPDATE_STAT); error=update_state_info(param, info,
((param->testflag & T_STATISTICS) ?
UPDATE_STAT : 0) |
((param->testflag & T_AUTO_INC) ?
UPDATE_AUTO_INC : 0));
} }
if ((!rep_quick && !error) || if ((!rep_quick && !error) ||
!(param->testflag & (T_FAST | T_FORCE_CREATE))) !(param->testflag & (T_FAST | T_FORCE_CREATE)))
...@@ -808,7 +802,8 @@ static int myisamchk(MI_CHECK *param, my_string filename) ...@@ -808,7 +802,8 @@ static int myisamchk(MI_CHECK *param, my_string filename)
error|=update_state_info(param, info, error|=update_state_info(param, info,
UPDATE_OPEN_COUNT | UPDATE_OPEN_COUNT |
(((param->testflag & (T_REP | T_REP_BY_SORT)) ? (((param->testflag & (T_REP | T_REP_BY_SORT)) ?
UPDATE_TIME | UPDATE_STAT : 0) | UPDATE_TIME : 0) |
(state_updated ? UPDATE_STAT : 0) |
((param->testflag & T_SORT_RECORDS) ? ((param->testflag & T_SORT_RECORDS) ?
UPDATE_SORT : 0))); UPDATE_SORT : 0)));
VOID(lock_file(param, share->kfile,0L,F_UNLCK,"indexfile",filename)); VOID(lock_file(param, share->kfile,0L,F_UNLCK,"indexfile",filename));
...@@ -1142,7 +1137,8 @@ static int mi_sort_records(MI_CHECK *param, ...@@ -1142,7 +1137,8 @@ static int mi_sort_records(MI_CHECK *param,
SORT_INFO *sort_info= &param->sort_info; SORT_INFO *sort_info= &param->sort_info;
DBUG_ENTER("sort_records"); DBUG_ENTER("sort_records");
bzero((char*) sort_info,sizeof(sort_info)); bzero((char*) sort_info,sizeof(*sort_info));
sort_info->param=param;
keyinfo= &share->keyinfo[sort_key]; keyinfo= &share->keyinfo[sort_key];
got_error=1; got_error=1;
temp_buff=0; temp_buff=0;
...@@ -1263,7 +1259,7 @@ err: ...@@ -1263,7 +1259,7 @@ err:
{ {
VOID(end_io_cache(&info->rec_cache)); VOID(end_io_cache(&info->rec_cache));
(void) my_close(new_file,MYF(MY_WME)); (void) my_close(new_file,MYF(MY_WME));
(void) my_raid_delete(param->temp_filename, share->base.raid_chunksize, (void) my_raid_delete(param->temp_filename, share->base.raid_chunks,
MYF(MY_WME)); MYF(MY_WME));
} }
if (temp_buff) if (temp_buff)
......
...@@ -575,6 +575,10 @@ enum myisam_log_commands { ...@@ -575,6 +575,10 @@ enum myisam_log_commands {
#define myisam_log_command(a,b,c,d,e) if (myisam_log_file >= 0) _myisam_log_command(a,b,c,d,e) #define myisam_log_command(a,b,c,d,e) if (myisam_log_file >= 0) _myisam_log_command(a,b,c,d,e)
#define myisam_log_record(a,b,c,d,e) if (myisam_log_file >= 0) _myisam_log_record(a,b,c,d,e) #define myisam_log_record(a,b,c,d,e) if (myisam_log_file >= 0) _myisam_log_record(a,b,c,d,e)
#ifdef __cplusplus
extern "C" {
#endif
extern uint _mi_get_block_info(MI_BLOCK_INFO *,File, my_off_t); extern uint _mi_get_block_info(MI_BLOCK_INFO *,File, my_off_t);
extern uint _mi_rec_pack(MI_INFO *info,byte *to,const byte *from); extern uint _mi_rec_pack(MI_INFO *info,byte *to,const byte *from);
extern uint _mi_pack_get_block_info(MI_INFO *mysql, MI_BLOCK_INFO *, File, extern uint _mi_pack_get_block_info(MI_INFO *mysql, MI_BLOCK_INFO *, File,
...@@ -626,11 +630,10 @@ int _mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len, ...@@ -626,11 +630,10 @@ int _mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len,
enum ha_rkey_function search_flag, bool raw_key); enum ha_rkey_function search_flag, bool raw_key);
my_bool check_table_is_closed(const char *name, const char *where); my_bool check_table_is_closed(const char *name, const char *where);
int mi_open_datafile(MI_INFO *info, MYISAM_SHARE *share);
int mi_open_keyfile(MYISAM_SHARE *share);
/* Functions needed by mi_check */ /* Functions needed by mi_check */
#ifdef __cplusplus
extern "C" {
#endif
void mi_check_print_error _VARARGS((MI_CHECK *param, const char *fmt,...)); void mi_check_print_error _VARARGS((MI_CHECK *param, const char *fmt,...));
void mi_check_print_warning _VARARGS((MI_CHECK *param, const char *fmt,...)); void mi_check_print_warning _VARARGS((MI_CHECK *param, const char *fmt,...));
void mi_check_print_info _VARARGS((MI_CHECK *param, const char *fmt,...)); void mi_check_print_info _VARARGS((MI_CHECK *param, const char *fmt,...));
......
...@@ -100,7 +100,7 @@ File create_temp_file(char *to, const char *dir, const char *prefix, ...@@ -100,7 +100,7 @@ File create_temp_file(char *to, const char *dir, const char *prefix,
return 1; return 1;
} }
strmov(to,dir); strmov(to,dir);
strmov(convert_dirname(to),prefix); strmov(convert_dirname(to),prefix_buff);
file=mkstemp(to); file=mkstemp(to);
} }
#elif defined(HAVE_TEMPNAM) #elif defined(HAVE_TEMPNAM)
......
...@@ -83,7 +83,7 @@ int pthread_create(pthread_t *thread_id, pthread_attr_t *attr, ...@@ -83,7 +83,7 @@ int pthread_create(pthread_t *thread_id, pthread_attr_t *attr,
attr->dwStackSize ? attr->dwStackSize : attr->dwStackSize ? attr->dwStackSize :
65535, (void*) map); 65535, (void*) map);
#else #else
hThread=(HANDLE)_beginthread(pthread_start, hThread=(HANDLE)_beginthread((void( __cdecl *)(void *)) pthread_start,
attr->dwStackSize ? attr->dwStackSize : attr->dwStackSize ? attr->dwStackSize :
65535, (void*) map); 65535, (void*) map);
#endif #endif
......
...@@ -51,7 +51,7 @@ $log_prog_args=join(" ", skip_arguments(\@ARGV,"comments","cmp","server", ...@@ -51,7 +51,7 @@ $log_prog_args=join(" ", skip_arguments(\@ARGV,"comments","cmp","server",
"user", "host", "database", "password", "user", "host", "database", "password",
"use-old-results","skip-test", "use-old-results","skip-test",
"machine", "dir", "suffix", "log")); "machine", "dir", "suffix", "log"));
GetOptions("skip-test=s","comments=s","cmp=s","server=s","user=s","host=s","database=s","password=s","loop-count=i","row-count=i","skip-create","skip-delete","verbose","fast-insert","lock-tables","debug","fast","force","field-count=i","regions=i","groups=i","time-limit=i","log","use-old-results","machine=s","dir=s","suffix=s","help","odbc","small-test","small-tables","small-key-tables","stage=i","old-headers","die-on-errors","create-options","hires") || usage(); GetOptions("skip-test=s","comments=s","cmp=s","server=s","user=s","host=s","database=s","password=s","loop-count=i","row-count=i","skip-create","skip-delete","verbose","fast-insert","lock-tables","debug","fast","force","field-count=i","regions=i","groups=i","time-limit=i","log","use-old-results","machine=s","dir=s","suffix=s","help","odbc","small-test","small-tables","small-key-tables","stage=i","old-headers","die-on-errors","create-options=s","hires") || usage();
usage() if ($opt_help); usage() if ($opt_help);
$server=get_server($opt_server,$opt_host,$opt_database,$opt_odbc, $server=get_server($opt_server,$opt_host,$opt_database,$opt_odbc,
...@@ -400,6 +400,11 @@ All benchmarks takes the following options: ...@@ -400,6 +400,11 @@ All benchmarks takes the following options:
with the same --cmp, you will get a test that is comparable between with the same --cmp, you will get a test that is comparable between
the different sql servers. the different sql servers.
--create-options=#
Extra argument to all create statements. If you for example want to
create all MySQL tables as BDB tables use:
--create-options=TYPE=BDB
--database (Default $opt_database) --database (Default $opt_database)
In which database the test tables are created. In which database the test tables are created.
......
...@@ -572,7 +572,7 @@ if ($limits->{'group_functions'}) ...@@ -572,7 +572,7 @@ if ($limits->{'group_functions'})
$loop_time=new Benchmark; $loop_time=new Benchmark;
$count=$estimated=0; $count=$estimated=0;
for ($tests=0 ; $tests < $small_loop_count ; $tests++) for ($tests=1 ; $tests <= $small_loop_count ; $tests++)
{ {
$count+=2; $count+=2;
fetch_all_rows($dbh,"select count(distinct dummy1) from bench1"); fetch_all_rows($dbh,"select count(distinct dummy1) from bench1");
...@@ -834,7 +834,7 @@ if ($limits->{'func_odbc_floor'} && $limits->{'left_outer_join'}) ...@@ -834,7 +834,7 @@ if ($limits->{'func_odbc_floor'} && $limits->{'left_outer_join'})
$count=$estimated=0; $count=$estimated=0;
$loop_time=new Benchmark; $loop_time=new Benchmark;
for ($i=0 ; $i < $small_loop_count ; $i++) for ($i=1 ; $i <= $small_loop_count ; $i++)
{ {
$count+=fetch_all_rows($dbh,"select count(a.dummy1),count(b.dummy1) from bench1 as a left outer join bench1 as b on (a.id2=b.id3) where b.id3 is null"); $count+=fetch_all_rows($dbh,"select count(a.dummy1),count(b.dummy1) from bench1 as a left outer join bench1 as b on (a.id2=b.id3) where b.id3 is null");
$end_time=new Benchmark; $end_time=new Benchmark;
......
...@@ -4574,6 +4574,7 @@ create_field::create_field(Field *old_field,Field *orig_field) ...@@ -4574,6 +4574,7 @@ create_field::create_field(Field *old_field,Field *orig_field)
interval= ((Field_enum*) old_field)->typelib; interval= ((Field_enum*) old_field)->typelib;
else else
interval=0; interval=0;
def=0;
if (!old_field->is_real_null() && ! (flags & BLOB_FLAG) && if (!old_field->is_real_null() && ! (flags & BLOB_FLAG) &&
old_field->type() != FIELD_TYPE_TIMESTAMP && old_field->ptr && old_field->type() != FIELD_TYPE_TIMESTAMP && old_field->ptr &&
orig_field) orig_field)
...@@ -4584,15 +4585,14 @@ create_field::create_field(Field *old_field,Field *orig_field) ...@@ -4584,15 +4585,14 @@ create_field::create_field(Field *old_field,Field *orig_field)
/* Get the value from record[2] (the default value row) */ /* Get the value from record[2] (the default value row) */
my_ptrdiff_t diff= (my_ptrdiff_t) (orig_field->table->rec_buff_length*2); my_ptrdiff_t diff= (my_ptrdiff_t) (orig_field->table->rec_buff_length*2);
orig_field->move_field(diff); // Points now at record[2] orig_field->move_field(diff); // Points now at record[2]
bool is_null=orig_field->is_real_null();
res=orig_field->val_str(&tmp,&tmp); res=orig_field->val_str(&tmp,&tmp);
orig_field->move_field(-diff); // Back to record[0] orig_field->move_field(-diff); // Back to record[0]
if (res) // If not NULL value if (!is_null)
{ {
pos= (char*) sql_memdup(tmp.ptr(),tmp.length()+1); pos= (char*) sql_memdup(tmp.ptr(),tmp.length()+1);
pos[tmp.length()]=0; pos[tmp.length()]=0;
def=new Item_string(pos,tmp.length()); def=new Item_string(pos,tmp.length());
} }
} }
else
def=0;
} }
...@@ -1472,11 +1472,11 @@ ha_rows ha_berkeley::records_in_range(int keynr, ...@@ -1472,11 +1472,11 @@ ha_rows ha_berkeley::records_in_range(int keynr,
DB_KEY_RANGE start_range, end_range; DB_KEY_RANGE start_range, end_range;
double start_pos,end_pos,rows; double start_pos,end_pos,rows;
DBUG_ENTER("records_in_range"); DBUG_ENTER("records_in_range");
if ((start_key && file->key_range(file,transaction, if ((start_key && file->key_range(key_file[keynr],transaction,
pack_key(&key, keynr, key_buff, start_key, pack_key(&key, keynr, key_buff, start_key,
start_key_len), start_key_len),
&start_range,0)) || &start_range,0)) ||
(end_key && file->key_range(file,transaction, (end_key && file->key_range(key_file[keynr],transaction,
pack_key(&key, keynr, key_buff, end_key, pack_key(&key, keynr, key_buff, end_key,
end_key_len), end_key_len),
&end_range,0))) &end_range,0)))
......
...@@ -35,7 +35,7 @@ ulong myisam_recover_options= HA_RECOVER_NONE; ...@@ -35,7 +35,7 @@ ulong myisam_recover_options= HA_RECOVER_NONE;
/* bits in myisam_recover_options */ /* bits in myisam_recover_options */
const char *myisam_recover_names[] = const char *myisam_recover_names[] =
{ "DEFAULT", "BACKUP", "FORCE"}; { "DEFAULT", "BACKUP", "FORCE", "QUICK"};
TYPELIB myisam_recover_typelib= {array_elements(myisam_recover_names),"", TYPELIB myisam_recover_typelib= {array_elements(myisam_recover_names),"",
myisam_recover_names}; myisam_recover_names};
...@@ -57,6 +57,8 @@ static void mi_check_print_msg(MI_CHECK *param, const char* msg_type, ...@@ -57,6 +57,8 @@ static void mi_check_print_msg(MI_CHECK *param, const char* msg_type,
my_vsnprintf(msgbuf, sizeof(msgbuf), fmt, args); my_vsnprintf(msgbuf, sizeof(msgbuf), fmt, args);
msgbuf[sizeof(msgbuf) - 1] = 0; // healthy paranoia msgbuf[sizeof(msgbuf) - 1] = 0; // healthy paranoia
DBUG_PRINT(msg_type,("message: %s",msgbuf));
if (thd->net.vio == 0) if (thd->net.vio == 0)
{ {
sql_print_error(msgbuf); sql_print_error(msgbuf);
...@@ -409,29 +411,44 @@ int ha_myisam::repair(THD* thd, HA_CHECK_OPT *check_opt) ...@@ -409,29 +411,44 @@ int ha_myisam::repair(THD* thd, HA_CHECK_OPT *check_opt)
int error; int error;
if (!file) return HA_ADMIN_INTERNAL_ERROR; if (!file) return HA_ADMIN_INTERNAL_ERROR;
MI_CHECK param; MI_CHECK param;
ha_rows start_records;
myisamchk_init(&param); myisamchk_init(&param);
param.thd = thd; param.thd = thd;
param.op_name = (char*) "repair"; param.op_name = (char*) "repair";
param.testflag = (check_opt->flags | T_SILENT | T_FORCE_CREATE | param.testflag = ((check_opt->flags | T_SILENT | T_FORCE_CREATE) |
T_REP_BY_SORT); (check_opt->flags & T_EXTEND ? T_REP : T_REP_BY_SORT));
if (check_opt->quick) if (check_opt->quick)
param.opt_rep_quick++; param.opt_rep_quick++;
param.sort_buffer_length= check_opt->sort_buffer_size; param.sort_buffer_length= check_opt->sort_buffer_size;
while ((error=repair(thd,param,0))) start_records=file->state->records;
while ((error=repair(thd,param,0)) && param.retry_repair)
{ {
param.retry_repair=0;
if (param.retry_without_quick && param.opt_rep_quick) if (param.retry_without_quick && param.opt_rep_quick)
{ {
param.opt_rep_quick=0; param.opt_rep_quick=0;
sql_print_error("Warning: Retrying recover of: %s without quick",
table->path);
continue; continue;
} }
if ((param.testflag & T_REP_BY_SORT)) if ((param.testflag & T_REP_BY_SORT))
{ {
param.testflag= (param.testflag & ~T_REP_BY_SORT) | T_REP; param.testflag= (param.testflag & ~T_REP_BY_SORT) | T_REP;
sql_print_error("Warning: Retrying recover of: %s with keycache",
table->path);
continue; continue;
} }
break; break;
} }
if (!error && start_records != file->state->records)
{
char llbuff[22],llbuff2[22];
sql_print_error("Warning: Found %s of %s rows from %s",
llstr(file->state->records, llbuff),
llstr(start_records, llbuff2),
table->path);
}
return error; return error;
} }
...@@ -455,17 +472,18 @@ int ha_myisam::optimize(THD* thd, HA_CHECK_OPT *check_opt) ...@@ -455,17 +472,18 @@ int ha_myisam::optimize(THD* thd, HA_CHECK_OPT *check_opt)
int ha_myisam::repair(THD *thd, MI_CHECK &param, bool optimize) int ha_myisam::repair(THD *thd, MI_CHECK &param, bool optimize)
{ {
int error=0; int error=0;
bool optimize_done= !optimize; bool optimize_done= !optimize, statistics_done=0;
char fixed_name[FN_REFLEN]; char fixed_name[FN_REFLEN];
const char *old_proc_info=thd->proc_info; const char *old_proc_info=thd->proc_info;
MYISAM_SHARE* share = file->s; MYISAM_SHARE* share = file->s;
DBUG_ENTER("ha_myisam::repair");
param.table_name = table->table_name; param.table_name = table->table_name;
param.tmpfile_createflag = O_RDWR | O_TRUNC; param.tmpfile_createflag = O_RDWR | O_TRUNC;
param.using_global_keycache = 1; param.using_global_keycache = 1;
param.thd=thd; param.thd=thd;
param.tmpdir=mysql_tmpdir; param.tmpdir=mysql_tmpdir;
param.out_flag=0;
VOID(fn_format(fixed_name,file->filename,"",MI_NAME_IEXT, VOID(fn_format(fixed_name,file->filename,"",MI_NAME_IEXT,
4+ (param.opt_follow_links ? 16 : 0))); 4+ (param.opt_follow_links ? 16 : 0)));
...@@ -475,15 +493,18 @@ int ha_myisam::repair(THD *thd, MI_CHECK &param, bool optimize) ...@@ -475,15 +493,18 @@ int ha_myisam::repair(THD *thd, MI_CHECK &param, bool optimize)
!(share->state.changed & STATE_NOT_OPTIMIZED_KEYS)))) !(share->state.changed & STATE_NOT_OPTIMIZED_KEYS))))
{ {
optimize_done=1; optimize_done=1;
if (mi_test_if_sort_rep(file,file->state->records,0)) if (mi_test_if_sort_rep(file,file->state->records,0) &&
(param.testflag & T_REP_BY_SORT))
{ {
param.testflag|= T_STATISTICS; // We get this for free param.testflag|= T_STATISTICS; // We get this for free
thd->proc_info="Repairing by sorting"; thd->proc_info="Repair by sorting";
statistics_done=1;
error = mi_repair_by_sort(&param, file, fixed_name, param.opt_rep_quick); error = mi_repair_by_sort(&param, file, fixed_name, param.opt_rep_quick);
} }
else else
{ {
thd->proc_info="Repairing"; thd->proc_info="Repair with keycache";
param.testflag &= ~T_REP_BY_SORT;
error= mi_repair(&param, file, fixed_name, param.opt_rep_quick); error= mi_repair(&param, file, fixed_name, param.opt_rep_quick);
} }
} }
...@@ -496,7 +517,7 @@ int ha_myisam::repair(THD *thd, MI_CHECK &param, bool optimize) ...@@ -496,7 +517,7 @@ int ha_myisam::repair(THD *thd, MI_CHECK &param, bool optimize)
thd->proc_info="Sorting index"; thd->proc_info="Sorting index";
error=mi_sort_index(&param,file,fixed_name); error=mi_sort_index(&param,file,fixed_name);
} }
if ((param.testflag & T_STATISTICS) && if (!statistics_done && (param.testflag & T_STATISTICS) &&
(share->state.changed & STATE_NOT_ANALYZED)) (share->state.changed & STATE_NOT_ANALYZED))
{ {
optimize_done=1; optimize_done=1;
...@@ -517,7 +538,7 @@ int ha_myisam::repair(THD *thd, MI_CHECK &param, bool optimize) ...@@ -517,7 +538,7 @@ int ha_myisam::repair(THD *thd, MI_CHECK &param, bool optimize)
if (file->s->base.auto_key) if (file->s->base.auto_key)
update_auto_increment_key(&param, file, 1); update_auto_increment_key(&param, file, 1);
error = update_state_info(&param, file, error = update_state_info(&param, file,
UPDATE_TIME | UPDATE_TIME | UPDATE_OPEN_COUNT |
(param.testflag & T_STATISTICS ? (param.testflag & T_STATISTICS ?
UPDATE_STAT : 0)); UPDATE_STAT : 0));
info(HA_STATUS_NO_LOCK | HA_STATUS_TIME | HA_STATUS_VARIABLE | info(HA_STATUS_NO_LOCK | HA_STATUS_TIME | HA_STATUS_VARIABLE |
...@@ -528,33 +549,9 @@ int ha_myisam::repair(THD *thd, MI_CHECK &param, bool optimize) ...@@ -528,33 +549,9 @@ int ha_myisam::repair(THD *thd, MI_CHECK &param, bool optimize)
mi_mark_crashed(file); mi_mark_crashed(file);
file->update |= HA_STATE_CHANGED | HA_STATE_ROW_CHANGED; file->update |= HA_STATE_CHANGED | HA_STATE_ROW_CHANGED;
} }
if (!error)
{
if (param.out_flag & (O_NEW_DATA | O_NEW_INDEX))
{
/*
We have to close all instances of this file to ensure that we can
do the rename safely on all operating system and to ensure that
all threads are using the new version.
*/
thd->proc_info="renaming file";
VOID(pthread_mutex_lock(&LOCK_open));
if (close_cached_table(thd,table))
error=1;
if (param.out_flag & O_NEW_DATA)
error|=change_to_newfile(fixed_name,MI_NAME_DEXT,
DATA_TMP_EXT, 0, MYF(0));
if (param.out_flag & O_NEW_INDEX)
error|=change_to_newfile(fixed_name,MI_NAME_IEXT,
INDEX_TMP_EXT, 0, MYF(0));
VOID(pthread_mutex_unlock(&LOCK_open));
}
}
thd->proc_info=old_proc_info; thd->proc_info=old_proc_info;
return (error ? HA_ADMIN_FAILED : DBUG_RETURN(error ? HA_ADMIN_FAILED :
!optimize_done ? HA_ADMIN_ALREADY_DONE : HA_ADMIN_OK); !optimize_done ? HA_ADMIN_ALREADY_DONE : HA_ADMIN_OK);
} }
...@@ -600,16 +597,19 @@ bool ha_myisam::check_and_repair(THD *thd) ...@@ -600,16 +597,19 @@ bool ha_myisam::check_and_repair(THD *thd)
DBUG_ENTER("ha_myisam::auto_check_and_repair"); DBUG_ENTER("ha_myisam::auto_check_and_repair");
check_opt.init(); check_opt.init();
check_opt.flags= T_MEDIUM; check_opt.flags= T_MEDIUM | T_AUTO_REPAIR;
check_opt.quick= !file->state->del; // Don't use quick if deleted rows // Don't use quick if deleted rows
if (!file->state->del && (myisam_recover_options & HA_RECOVER_QUICK))
check_opt.quick=1;
sql_print_error("Warning: Checking table: %s",table->path);
if (mi_is_crashed(file) || check(thd, &check_opt)) if (mi_is_crashed(file) || check(thd, &check_opt))
{ {
if (check_opt.retry_without_quick) sql_print_error("Warning: Recovering table: %s",table->path);
check_opt.quick=0; check_opt.quick= !check_opt.retry_without_quick;
check_opt.flags=(((myisam_recover_options & HA_RECOVER_BACKUP) ? check_opt.flags=(((myisam_recover_options & HA_RECOVER_BACKUP) ?
T_BACKUP_DATA : 0) | T_BACKUP_DATA : 0) |
(!(myisam_recover_options & HA_RECOVER_FORCE) ? (!(myisam_recover_options & HA_RECOVER_FORCE) ?
T_SAFE_REPAIR : 0)); T_SAFE_REPAIR : 0)) | T_AUTO_REPAIR;
if (repair(thd, &check_opt)) if (repair(thd, &check_opt))
error=1; error=1;
} }
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#define HA_RECOVER_DEFAULT 1 // Automatic recover active #define HA_RECOVER_DEFAULT 1 // Automatic recover active
#define HA_RECOVER_BACKUP 2 // Make a backupfile on recover #define HA_RECOVER_BACKUP 2 // Make a backupfile on recover
#define HA_RECOVER_FORCE 4 // Recover even if we loose rows #define HA_RECOVER_FORCE 4 // Recover even if we loose rows
#define HA_RECOVER_QUICK 8 // Don't check rows in data file
extern ulong myisam_sort_buffer_size; extern ulong myisam_sort_buffer_size;
extern TYPELIB myisam_recover_typelib; extern TYPELIB myisam_recover_typelib;
......
...@@ -32,6 +32,9 @@ ...@@ -32,6 +32,9 @@
#ifdef HAVE_BERKELEY_DB #ifdef HAVE_BERKELEY_DB
#include "ha_berkeley.h" #include "ha_berkeley.h"
#endif #endif
#ifdef HAVE_INNOBASE_DB
#include "ha_innobase.h"
#endif
#include <myisampack.h> #include <myisampack.h>
#include <errno.h> #include <errno.h>
...@@ -46,7 +49,7 @@ ulong ha_read_count, ha_write_count, ha_delete_count, ha_update_count, ...@@ -46,7 +49,7 @@ ulong ha_read_count, ha_write_count, ha_delete_count, ha_update_count,
const char *ha_table_type[] = { const char *ha_table_type[] = {
"", "DIAB_ISAM","HASH","MISAM","PISAM","RMS_ISAM","HEAP", "ISAM", "", "DIAB_ISAM","HASH","MISAM","PISAM","RMS_ISAM","HEAP", "ISAM",
"MRG_ISAM","MYISAM", "MRG_MYISAM", "BERKELEY_DB?", "?", "?",NullS "MRG_ISAM","MYISAM", "MRG_MYISAM", "BDB", "INNOBASE", "?", "?",NullS
}; };
const char *ha_row_type[] = { const char *ha_row_type[] = {
...@@ -66,6 +69,10 @@ enum db_type ha_checktype(enum db_type database_type) ...@@ -66,6 +69,10 @@ enum db_type ha_checktype(enum db_type database_type)
case DB_TYPE_BERKELEY_DB: case DB_TYPE_BERKELEY_DB:
return(berkeley_skip ? DB_TYPE_MYISAM : database_type); return(berkeley_skip ? DB_TYPE_MYISAM : database_type);
#endif #endif
#ifdef HAVE_INNOBASE_DB
case DB_TYPE_INNOBASE:
return(innobase_skip ? DB_TYPE_MYISAM : database_type);
#endif
#ifndef NO_HASH #ifndef NO_HASH
case DB_TYPE_HASH: case DB_TYPE_HASH:
#endif #endif
...@@ -103,6 +110,10 @@ handler *get_new_handler(TABLE *table, enum db_type db_type) ...@@ -103,6 +110,10 @@ handler *get_new_handler(TABLE *table, enum db_type db_type)
#ifdef HAVE_BERKELEY_DB #ifdef HAVE_BERKELEY_DB
case DB_TYPE_BERKELEY_DB: case DB_TYPE_BERKELEY_DB:
return new ha_berkeley(table); return new ha_berkeley(table);
#endif
#ifdef HAVE_INNOBASE_DB
case DB_TYPE_INNOBASE_DB:
return new ha_innobase(table);
#endif #endif
case DB_TYPE_HEAP: case DB_TYPE_HEAP:
return new ha_heap(table); return new ha_heap(table);
...@@ -123,6 +134,14 @@ int ha_init() ...@@ -123,6 +134,14 @@ int ha_init()
if ((error=berkeley_init())) if ((error=berkeley_init()))
return error; return error;
} }
#endif
#ifdef HAVE_INNOBASE_DB
if (!innobase_skip)
{
int error;
if ((error=innobase_init()))
return error;
}
#endif #endif
return 0; return 0;
} }
...@@ -146,6 +165,10 @@ int ha_panic(enum ha_panic_function flag) ...@@ -146,6 +165,10 @@ int ha_panic(enum ha_panic_function flag)
#ifdef HAVE_BERKELEY_DB #ifdef HAVE_BERKELEY_DB
if (!berkeley_skip) if (!berkeley_skip)
error|=berkeley_end(); error|=berkeley_end();
#endif
#ifdef HAVE_INNOBASE_DB
if (!innobase_skip)
error|=innobase_end();
#endif #endif
return error; return error;
} /* ha_panic */ } /* ha_panic */
...@@ -154,7 +177,7 @@ int ha_panic(enum ha_panic_function flag) ...@@ -154,7 +177,7 @@ int ha_panic(enum ha_panic_function flag)
int ha_autocommit_or_rollback(THD *thd, int error) int ha_autocommit_or_rollback(THD *thd, int error)
{ {
DBUG_ENTER("ha_autocommit_or_rollback"); DBUG_ENTER("ha_autocommit_or_rollback");
#ifdef HAVE_BERKELEY_DB #if defined(HAVE_BERKELEY_DB) || defined(HAVE_INNOBASE_DB)
if ((thd->options & OPTION_AUTO_COMMIT) && !thd->locked_tables) if ((thd->options & OPTION_AUTO_COMMIT) && !thd->locked_tables)
{ {
if (!error) if (!error)
...@@ -183,6 +206,17 @@ int ha_commit(THD *thd) ...@@ -183,6 +206,17 @@ int ha_commit(THD *thd)
error=1; error=1;
} }
} }
#endif
#ifdef HAVE_INNOBASE_DB
if (thd->transaction.innobase_tid)
{
int error=innobase_commit(thd);
if (error)
{
my_error(ER_ERROR_DURING_COMMIT, MYF(0), error);
error=1;
}
}
#endif #endif
DBUG_RETURN(error); DBUG_RETURN(error);
} }
...@@ -201,6 +235,17 @@ int ha_rollback(THD *thd) ...@@ -201,6 +235,17 @@ int ha_rollback(THD *thd)
error=1; error=1;
} }
} }
#endif
#ifdef HAVE_INNOBASE_DB
if (thd->transaction.innobase_tid)
{
int error=innobase_rollback(thd);
if (error)
{
my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), error);
error=1;
}
}
#endif #endif
DBUG_RETURN(error); DBUG_RETURN(error);
} }
...@@ -212,6 +257,10 @@ bool ha_flush_logs() ...@@ -212,6 +257,10 @@ bool ha_flush_logs()
#ifdef HAVE_BERKELEY_DB #ifdef HAVE_BERKELEY_DB
if (!berkeley_skip && berkeley_flush_logs()) if (!berkeley_skip && berkeley_flush_logs())
result=1; result=1;
#endif
#ifdef HAVE_INNOBASE_DB
if (!innobase_skip && innobase_flush_logs())
result=1;
#endif #endif
return result; return result;
} }
......
...@@ -448,7 +448,7 @@ skipp: ...@@ -448,7 +448,7 @@ skipp:
res->replace((uint) offset,from_length,*res3); res->replace((uint) offset,from_length,*res3);
offset+=(int) to_length; offset+=(int) to_length;
} }
while ((offset=res->strstr(*res2,(uint) offset)) >0); while ((offset=res->strstr(*res2,(uint) offset)) >= 0);
return res; return res;
null: null:
...@@ -768,7 +768,7 @@ String *Item_func_substr_index::val_str(String *str) ...@@ -768,7 +768,7 @@ String *Item_func_substr_index::val_str(String *str)
} }
else else
{ // Start counting at end { // Start counting at end
for (offset=res->length() ; ; offset-=delimeter_length) for (offset=res->length() ; ; offset-=delimeter_length-1)
{ {
if ((int) (offset=res->strrstr(*delimeter,offset)) < 0) if ((int) (offset=res->strrstr(*delimeter,offset)) < 0)
return res; // Didn't find, return org string return res; // Didn't find, return org string
......
...@@ -308,7 +308,7 @@ public: ...@@ -308,7 +308,7 @@ public:
Start_log_event() :Log_event(time(NULL)),binlog_version(BINLOG_VERSION) Start_log_event() :Log_event(time(NULL)),binlog_version(BINLOG_VERSION)
{ {
created = when; created = (uint32) when;
memcpy(server_version, ::server_version, sizeof(server_version)); memcpy(server_version, ::server_version, sizeof(server_version));
} }
Start_log_event(FILE* file, time_t when_arg, uint32 server_id) : Start_log_event(FILE* file, time_t when_arg, uint32 server_id) :
......
...@@ -21,6 +21,9 @@ ...@@ -21,6 +21,9 @@
#ifdef HAVE_BERKELEY_DB #ifdef HAVE_BERKELEY_DB
#include "ha_berkeley.h" #include "ha_berkeley.h"
#endif #endif
#ifdef HAVE_INNOBASE_DB
#include "ha_innobase.h"
#endif
#include "ha_myisam.h" #include "ha_myisam.h"
#include <nisam.h> #include <nisam.h>
#include <thr_alarm.h> #include <thr_alarm.h>
...@@ -147,8 +150,7 @@ static ulong opt_specialflag=SPECIAL_ENGLISH; ...@@ -147,8 +150,7 @@ static ulong opt_specialflag=SPECIAL_ENGLISH;
static my_socket unix_sock= INVALID_SOCKET,ip_sock= INVALID_SOCKET; static my_socket unix_sock= INVALID_SOCKET,ip_sock= INVALID_SOCKET;
static ulong back_log,connect_timeout,concurrency; static ulong back_log,connect_timeout,concurrency;
static my_string opt_logname=0,opt_update_logname=0, static my_string opt_logname=0,opt_update_logname=0,
opt_binlog_index_name = 0,opt_slow_logname=0; opt_binlog_index_name = 0,opt_slow_logname=0;
my_string opt_bin_logname = 0; // this one needs to be seen in sql_parse.cc
static char mysql_home[FN_REFLEN],pidfile_name[FN_REFLEN]; static char mysql_home[FN_REFLEN],pidfile_name[FN_REFLEN];
static pthread_t select_thread; static pthread_t select_thread;
static pthread_t flush_thread; // Used when debugging static pthread_t flush_thread; // Used when debugging
...@@ -231,9 +233,11 @@ char mysql_real_data_home[FN_REFLEN], ...@@ -231,9 +233,11 @@ char mysql_real_data_home[FN_REFLEN],
default_charset[LIBLEN],mysql_charsets_dir[FN_REFLEN], *charsets_list, default_charset[LIBLEN],mysql_charsets_dir[FN_REFLEN], *charsets_list,
blob_newline,f_fyllchar,max_sort_char,*mysqld_user,*mysqld_chroot, blob_newline,f_fyllchar,max_sort_char,*mysqld_user,*mysqld_chroot,
*opt_init_file; *opt_init_file;
char *opt_bin_logname = 0; // this one needs to be seen in sql_parse.cc
char server_version[50]=MYSQL_SERVER_VERSION; char server_version[50]=MYSQL_SERVER_VERSION;
const char *first_keyword="first"; const char *first_keyword="first";
const char **errmesg; /* Error messages */ const char **errmesg; /* Error messages */
const char *myisam_recover_options_str="OFF";
byte last_ref[MAX_REFLENGTH]; /* Index ref of keys */ byte last_ref[MAX_REFLENGTH]; /* Index ref of keys */
my_string mysql_unix_port=NULL,mysql_tmpdir=NULL; my_string mysql_unix_port=NULL,mysql_tmpdir=NULL;
ulong my_bind_addr; /* the address we bind to */ ulong my_bind_addr; /* the address we bind to */
...@@ -2219,7 +2223,8 @@ enum options { ...@@ -2219,7 +2223,8 @@ enum options {
OPT_LOG_SLAVE_UPDATES, OPT_BINLOG_DO_DB, OPT_LOG_SLAVE_UPDATES, OPT_BINLOG_DO_DB,
OPT_BINLOG_IGNORE_DB, OPT_WANT_CORE, OPT_BINLOG_IGNORE_DB, OPT_WANT_CORE,
OPT_SKIP_CONCURRENT_INSERT, OPT_MEMLOCK, OPT_MYISAM_RECOVER, OPT_SKIP_CONCURRENT_INSERT, OPT_MEMLOCK, OPT_MYISAM_RECOVER,
OPT_REPLICATE_REWRITE_DB, OPT_SERVER_ID, OPT_SKIP_SLAVE_START OPT_REPLICATE_REWRITE_DB, OPT_SERVER_ID, OPT_SKIP_SLAVE_START,
OPT_SKIP_INNOBASE
}; };
static struct option long_options[] = { static struct option long_options[] = {
...@@ -2292,6 +2297,9 @@ static struct option long_options[] = { ...@@ -2292,6 +2297,9 @@ static struct option long_options[] = {
{"set-variable", required_argument, 0, 'O'}, {"set-variable", required_argument, 0, 'O'},
#ifdef HAVE_BERKELEY_DB #ifdef HAVE_BERKELEY_DB
{"skip-bdb", no_argument, 0, (int) OPT_BDB_SKIP}, {"skip-bdb", no_argument, 0, (int) OPT_BDB_SKIP},
#endif
#ifdef HAVE_INNOBASE_DB
{"skip-innobase", no_argument, 0, (int) OPT_INNOBASE_SKIP},
#endif #endif
{"skip-concurrent-insert", no_argument, 0, (int) OPT_SKIP_CONCURRENT_INSERT}, {"skip-concurrent-insert", no_argument, 0, (int) OPT_SKIP_CONCURRENT_INSERT},
{"skip-delay-key-write", no_argument, 0, (int) OPT_SKIP_DELAY_KEY_WRITE}, {"skip-delay-key-write", no_argument, 0, (int) OPT_SKIP_DELAY_KEY_WRITE},
...@@ -2443,6 +2451,7 @@ struct show_var_st init_vars[]= { ...@@ -2443,6 +2451,7 @@ struct show_var_st init_vars[]= {
{"max_sort_length", (char*) &max_item_sort_length, SHOW_LONG}, {"max_sort_length", (char*) &max_item_sort_length, SHOW_LONG},
{"max_tmp_tables", (char*) &max_tmp_tables, SHOW_LONG}, {"max_tmp_tables", (char*) &max_tmp_tables, SHOW_LONG},
{"max_write_lock_count", (char*) &max_write_lock_count, SHOW_LONG}, {"max_write_lock_count", (char*) &max_write_lock_count, SHOW_LONG},
{"myisam_recover_options", (char*) &myisam_recover_options_str, SHOW_CHAR_PTR},
{"myisam_sort_buffer_size", (char*) &myisam_sort_buffer_size, SHOW_LONG}, {"myisam_sort_buffer_size", (char*) &myisam_sort_buffer_size, SHOW_LONG},
{"net_buffer_length", (char*) &net_buffer_length, SHOW_LONG}, {"net_buffer_length", (char*) &net_buffer_length, SHOW_LONG},
{"net_retry_count", (char*) &mysqld_net_retry_count, SHOW_LONG}, {"net_retry_count", (char*) &mysqld_net_retry_count, SHOW_LONG},
...@@ -2647,6 +2656,11 @@ static void usage(void) ...@@ -2647,6 +2656,11 @@ static void usage(void)
--bdb-tmpdir=directory Berkeley DB tempfile name\n\ --bdb-tmpdir=directory Berkeley DB tempfile name\n\
--skip-bdb Don't use berkeley db (will save memory)\n\ --skip-bdb Don't use berkeley db (will save memory)\n\
"); ");
#endif
#ifdef HAVE_INNOBASE_DB
puts("\
--skip-innobase Don't use innobase (will save memory)\n\
");
#endif #endif
print_defaults("my",load_default_groups); print_defaults("my",load_default_groups);
puts(""); puts("");
...@@ -2917,11 +2931,13 @@ static void get_options(int argc,char **argv) ...@@ -2917,11 +2931,13 @@ static void get_options(int argc,char **argv)
myisam_delay_key_write=0; myisam_delay_key_write=0;
myisam_concurrent_insert=0; myisam_concurrent_insert=0;
myisam_recover_options= HA_RECOVER_NONE; myisam_recover_options= HA_RECOVER_NONE;
ha_open_options&= ~HA_OPEN_ABORT_IF_CRASHED;
break; break;
case (int) OPT_SAFE: case (int) OPT_SAFE:
opt_specialflag|= SPECIAL_SAFE_MODE; opt_specialflag|= SPECIAL_SAFE_MODE;
myisam_delay_key_write=0; myisam_delay_key_write=0;
myisam_recover_options= HA_RECOVER_NONE; // To be changed myisam_recover_options= HA_RECOVER_NONE; // To be changed
ha_open_options&= ~HA_OPEN_ABORT_IF_CRASHED;
break; break;
case (int) OPT_SKIP_CONCURRENT_INSERT: case (int) OPT_SKIP_CONCURRENT_INSERT:
myisam_concurrent_insert=0; myisam_concurrent_insert=0;
...@@ -3085,17 +3101,30 @@ static void get_options(int argc,char **argv) ...@@ -3085,17 +3101,30 @@ static void get_options(int argc,char **argv)
case OPT_BDB_SKIP: case OPT_BDB_SKIP:
berkeley_skip=1; berkeley_skip=1;
break; break;
#endif
#ifdef HAVE_INNOBASE_DB
case OPT_INNOBASE_SKIP:
innobase_skip=1;
break;
#endif #endif
case OPT_MYISAM_RECOVER: case OPT_MYISAM_RECOVER:
{ {
if (!optarg || !optarg[0]) if (!optarg || !optarg[0])
myisam_recover_options=HA_RECOVER_DEFAULT;
else if ((myisam_recover_options=
find_bit_type(optarg, &myisam_recover_typelib)) == ~(ulong) 0)
{ {
fprintf(stderr, "Unknown option to myisam-recover: %s\n",optarg); myisam_recover_options= HA_RECOVER_DEFAULT;
exit(1); myisam_recover_options_str= myisam_recover_typelib.type_names[0];
}
else
{
myisam_recover_options_str=optarg;
if ((myisam_recover_options=
find_bit_type(optarg, &myisam_recover_typelib)) == ~(ulong) 0)
{
fprintf(stderr, "Unknown option to myisam-recover: %s\n",optarg);
exit(1);
}
} }
ha_open_options|=HA_OPEN_ABORT_IF_CRASHED;
break; break;
} }
case OPT_MASTER_HOST: case OPT_MASTER_HOST:
......
...@@ -706,7 +706,7 @@ TABLE *open_table(THD *thd,const char *db,const char *table_name, ...@@ -706,7 +706,7 @@ TABLE *open_table(THD *thd,const char *db,const char *table_name,
/* make a new table */ /* make a new table */
if (!(table=(TABLE*) my_malloc(sizeof(*table),MYF(MY_WME)))) if (!(table=(TABLE*) my_malloc(sizeof(*table),MYF(MY_WME))))
DBUG_RETURN(NULL); DBUG_RETURN(NULL);
if (open_unireg_entry(thd, table,db,table_name,alias,0) || if (open_unireg_entry(thd, table,db,table_name,alias,1) ||
!(table->table_cache_key=memdup_root(&table->mem_root,(char*) key, !(table->table_cache_key=memdup_root(&table->mem_root,(char*) key,
key_length))) key_length)))
{ {
...@@ -1157,7 +1157,6 @@ static int open_unireg_entry(THD *thd, TABLE *entry, const char *db, ...@@ -1157,7 +1157,6 @@ static int open_unireg_entry(THD *thd, TABLE *entry, const char *db,
thd->net.last_error[0]=0; // Clear error message thd->net.last_error[0]=0; // Clear error message
thd->net.last_errno=0; thd->net.last_errno=0;
error=0; error=0;
sql_print_error("Warning: Repairing table: %s.%s",db,name);
if (openfrm(path,alias, if (openfrm(path,alias,
(uint) (HA_OPEN_KEYFILE | HA_OPEN_RNDFILE | HA_GET_INDEX | (uint) (HA_OPEN_KEYFILE | HA_OPEN_RNDFILE | HA_GET_INDEX |
HA_TRY_READ_ONLY), HA_TRY_READ_ONLY),
...@@ -1166,12 +1165,22 @@ static int open_unireg_entry(THD *thd, TABLE *entry, const char *db, ...@@ -1166,12 +1165,22 @@ static int open_unireg_entry(THD *thd, TABLE *entry, const char *db,
entry) || entry) ||
(entry->file->is_crashed() && entry->file->check_and_repair(thd))) (entry->file->is_crashed() && entry->file->check_and_repair(thd)))
{ {
/* Give right error message */
thd->net.last_error[0]=0;
thd->net.last_errno=0;
entry->file->print_error(HA_ERR_CRASHED,MYF(0));
sql_print_error("Error: Couldn't repair table: %s.%s",db,name); sql_print_error("Error: Couldn't repair table: %s.%s",db,name);
closefrm(entry);
error=1; error=1;
} }
else
{
thd->net.last_error[0]=0; // Clear error message
thd->net.last_errno=0;
}
unlock_table_name(thd,&table_list); unlock_table_name(thd,&table_list);
if (locked) if (locked)
pthread_mutex_lock(&LOCK_open); // Get back old lock pthread_mutex_lock(&LOCK_open); // Get back original lock
if (error) if (error)
goto err; goto err;
} }
......
...@@ -501,6 +501,8 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name, ...@@ -501,6 +501,8 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
if ((create_info->options & HA_LEX_CREATE_TMP_TABLE) if ((create_info->options & HA_LEX_CREATE_TMP_TABLE)
&& find_temporary_table(thd,db,table_name)) && find_temporary_table(thd,db,table_name))
{ {
if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
DBUG_RETURN(0);
my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name); my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
DBUG_RETURN(-1); DBUG_RETURN(-1);
} }
...@@ -887,6 +889,24 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables, ...@@ -887,6 +889,24 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables,
continue; continue;
} }
/* Close all instances of the table to allow repair to rename files */
if (open_for_modify && table->table->version)
{
pthread_mutex_lock(&LOCK_open);
mysql_lock_abort(thd,table->table);
while (remove_table_from_cache(thd, table->table->table_cache_key,
table->table->real_name) &&
! thd->killed)
{
dropping_tables++;
(void) pthread_cond_wait(&COND_refresh,&LOCK_open);
dropping_tables--;
}
pthread_mutex_unlock(&LOCK_open);
if (thd->killed)
goto err;
}
int result_code = (table->table->file->*operator_func)(thd, check_opt); int result_code = (table->table->file->*operator_func)(thd, check_opt);
packet->length(0); packet->length(0);
net_store_data(packet, table_name); net_store_data(packet, table_name);
...@@ -931,7 +951,7 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables, ...@@ -931,7 +951,7 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables,
break; break;
} }
if (fatal_error) if (fatal_error)
table->table->flush_version=0; // Force close of table table->table->version=0; // Force close of table
close_thread_tables(thd); close_thread_tables(thd);
if (my_net_write(&thd->net, (char*) packet->ptr(), if (my_net_write(&thd->net, (char*) packet->ptr(),
packet->length())) packet->length()))
......
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