Commit 09dce662 authored by monty@tik.mysql.com's avatar monty@tik.mysql.com

Automatic repair of MyISAM tables + portability fixes

parent 16f11f94
monty@tramp.mysql.fi monty@tik.mysql.com
monty@donna.mysql.com
...@@ -315,7 +315,7 @@ Is There Anything Special to Do when Upgrading/Downgrading MySQL? ...@@ -315,7 +315,7 @@ Is There Anything Special to Do when Upgrading/Downgrading MySQL?
How Standards-compatible Is MySQL? How Standards-compatible Is MySQL?
* Extensions to ANSI:: @strong{MySQL} extensions to ANSI SQL92 * Extensions to ANSI:: @strong{MySQL} extensions to ANSI SQL92
* Ansi mode:: Running @strong{MySQL} in ANSI mode * ANSI mode:: Running @strong{MySQL} in ANSI mode
* Differences from ANSI:: @strong{MySQL} differences compared to ANSI SQL92 * Differences from ANSI:: @strong{MySQL} differences compared to ANSI SQL92
* Missing functions:: Functionality missing from @strong{MySQL} * Missing functions:: Functionality missing from @strong{MySQL}
* Standards:: What standards does @strong{MySQL} follow? * Standards:: What standards does @strong{MySQL} follow?
...@@ -1550,7 +1550,8 @@ clauses. Support for group functions (@code{COUNT()}, ...@@ -1550,7 +1550,8 @@ clauses. Support for group functions (@code{COUNT()},
@code{MAX()} and @code{MIN()}). @code{MAX()} and @code{MIN()}).
@item @item
Support for @code{LEFT OUTER JOIN} with ANSI SQL and ODBC syntax. Support for @code{LEFT OUTER JOIN} and @code{RIGHT OUTER JOIN} with ANSI
SQL and ODBC syntax.
@item @item
You can mix tables from different databases in the same query (as of You can mix tables from different databases in the same query (as of
...@@ -6024,6 +6025,16 @@ you are probably using @code{gcc} (or using an old binary compiled with ...@@ -6024,6 +6025,16 @@ you are probably using @code{gcc} (or using an old binary compiled with
/usr/bin/perl: can't resolve symbol '__divdi3' /usr/bin/perl: can't resolve symbol '__divdi3'
@end example @end example
Add @code{-L/usr/lib/gcc-lib/... -lgcc} to the link command when the
@file{mysql.so} library gets built (check the output from @code{make} for
@file{mysql.so} when you compile the Perl client). The @code{-L} option
should specify the pathname of the directory where @file{libgcc.a} is located
on your system.
Another cause of this problem may be that Perl and @strong{MySQL} aren't both
compiled with @code{gcc}. In this case, you can solve the mismatch by
compiling both with @code{gcc}.
If you get the following error from @code{Msql-Mysql-modules} If you get the following error from @code{Msql-Mysql-modules}
when you run the tests: when you run the tests:
...@@ -6032,7 +6043,8 @@ t/00base............install_driver(mysql) failed: Can't load '../blib/arch/auto/ ...@@ -6032,7 +6043,8 @@ t/00base............install_driver(mysql) failed: Can't load '../blib/arch/auto/
@end example @end example
it means that you need to include the compression library, -lz, to the it means that you need to include the compression library, -lz, to the
link line. This can be done by changing the line: link line. This can be doing the following change in the file
@file{lib/DBD/mysql/Install.pm}:
@example @example
$sysliblist .= " -lm"; $sysliblist .= " -lm";
...@@ -6042,20 +6054,9 @@ to ...@@ -6042,20 +6054,9 @@ to
$sysliblist .= " -lm -lz"; $sysliblist .= " -lm -lz";
@end example @end example
in file lib/DBD/mysql/Install.pm in the Msql-Mysql-modules directory.
After this, you MUST run 'make realclean' and then proceed with the After this, you MUST run 'make realclean' and then proceed with the
installation from the beginning. installation from the beginning.
Add @code{-L/usr/lib/gcc-lib/... -lgcc} to the link command when the
@file{mysql.so} library gets built (check the output from @code{make} for
@file{mysql.so} when you compile the Perl client). The @code{-L} option
should specify the pathname of the directory where @file{libgcc.a} is located
on your system.
Another cause of this problem may be that Perl and @strong{MySQL} aren't both
compiled with @code{gcc}. In this case, you can solve the mismatch by
compiling both with @code{gcc}.
If you want to use the Perl module on a system that doesn't support dynamic If you want to use the Perl module on a system that doesn't support dynamic
linking (like SCO) you can generate a static version of Perl that includes linking (like SCO) you can generate a static version of Perl that includes
@code{DBI} and @code{DBD-mysql}. The way this works is that you generate a @code{DBI} and @code{DBD-mysql}. The way this works is that you generate a
...@@ -8931,7 +8932,7 @@ The @code{mysql.server} script uses the following variables: ...@@ -8931,7 +8932,7 @@ The @code{mysql.server} script uses the following variables:
@table @code @table @code
@item --ansi @item --ansi
Use ANSI SQL syntax instead of MySQL syntax. @xref{Ansi mode}. Use ANSI SQL syntax instead of MySQL syntax. @xref{ANSI mode}.
@item -b, --basedir=path @item -b, --basedir=path
Path to installation directory. All paths are Path to installation directory. All paths are
...@@ -9631,14 +9632,14 @@ information. ...@@ -9631,14 +9632,14 @@ information.
@menu @menu
* Extensions to ANSI:: @strong{MySQL} extensions to ANSI SQL92 * Extensions to ANSI:: @strong{MySQL} extensions to ANSI SQL92
* Ansi mode:: Running @strong{MySQL} in ANSI mode * ANSI mode:: Running @strong{MySQL} in ANSI mode
* Differences from ANSI:: @strong{MySQL} differences compared to ANSI SQL92 * Differences from ANSI:: @strong{MySQL} differences compared to ANSI SQL92
* Missing functions:: Functionality missing from @strong{MySQL} * Missing functions:: Functionality missing from @strong{MySQL}
* Standards:: What standards does @strong{MySQL} follow? * Standards:: What standards does @strong{MySQL} follow?
* Commit-rollback:: How to cope without @code{COMMIT}-@code{ROLLBACK} * Commit-rollback:: How to cope without @code{COMMIT}-@code{ROLLBACK}
@end menu @end menu
@node Extensions to ANSI, Ansi mode, Compatibility, Compatibility @node Extensions to ANSI, ANSI mode, Compatibility, Compatibility
@section MySQL Extensions to ANSI SQL92 @section MySQL Extensions to ANSI SQL92
@strong{MySQL} includes some extensions that you probably will not find in @strong{MySQL} includes some extensions that you probably will not find in
...@@ -9882,7 +9883,7 @@ SELECT @@t1:=(@@t2:=1)+@@t3:=4,@@t1,@@t2,@@t3; ...@@ -9882,7 +9883,7 @@ SELECT @@t1:=(@@t2:=1)+@@t3:=4,@@t1,@@t2,@@t3;
@end itemize @end itemize
@node Ansi mode, Differences from ANSI, Extensions to ANSI, Compatibility @node ANSI mode, Differences from ANSI, Extensions to ANSI, Compatibility
@section Running MySQL in ANSI Mode @section Running MySQL in ANSI Mode
@cindex running, ANSI mode @cindex running, ANSI mode
@cindex ANSI mode, running @cindex ANSI mode, running
...@@ -9895,7 +9896,7 @@ of @strong{MySQL} changes: ...@@ -9895,7 +9896,7 @@ of @strong{MySQL} changes:
@code{||} is string concatenation instead of @code{OR}. @code{||} is string concatenation instead of @code{OR}.
@item @item
You can have any number of spaces between a function name and the @samp{(}. You can have any number of spaces between a function name and the @samp{(}.
This makes also all function names reserved words. This forces all function names to be treated as reserved words.
@item @item
@samp{"} will be an identifier quote character (like the @strong{MySQL} @samp{"} will be an identifier quote character (like the @strong{MySQL}
@samp{`} quote character) and not a string quote character. @samp{`} quote character) and not a string quote character.
...@@ -9904,7 +9905,7 @@ This makes also all function names reserved words. ...@@ -9904,7 +9905,7 @@ This makes also all function names reserved words.
@code{DOUBLE}. @code{DOUBLE}.
@end itemize @end itemize
@node Differences from ANSI, Missing functions, Ansi mode, Compatibility @node Differences from ANSI, Missing functions, ANSI mode, Compatibility
@section MySQL Differences Compared to ANSI SQL92 @section MySQL Differences Compared to ANSI SQL92
We try to make @strong{MySQL} follow the ANSI SQL standard and the We try to make @strong{MySQL} follow the ANSI SQL standard and the
...@@ -9913,7 +9914,8 @@ differently: ...@@ -9913,7 +9914,8 @@ differently:
@itemize @bullet @itemize @bullet
@item @item
@code{--} is only a comment if followed by a white space. @xref{Missing comments}. @code{--} is only a comment if followed by a white space. @xref{Missing
comments}.
@item @item
For @code{VARCHAR} columns, trailing spaces are removed when the value is For @code{VARCHAR} columns, trailing spaces are removed when the value is
stored. @xref{Bugs}. stored. @xref{Bugs}.
...@@ -9936,11 +9938,11 @@ extra conditions in this case. ...@@ -9936,11 +9938,11 @@ extra conditions in this case.
@cindex functionality, missing @cindex functionality, missing
The following functionality is missing in the current version of The following functionality is missing in the current version of
@strong{MySQL}. For a prioritized list indicating when new extensions may be @strong{MySQL}. For a prioritized list indicating when new extensions
added to @strong{MySQL}, you should consult may be added to @strong{MySQL}, you should consult
@uref{http://www.mysql.com/documentation/manual.php?section=TODO, the online @uref{http://www.mysql.com/documentation/manual.php?section=TODO, the
@strong{MySQL} TODO list}. That is the latest version of the TODO list in online @strong{MySQL} TODO list}. That is the latest version of the TODO
this manual. @xref{TODO}. list in this manual. @xref{TODO}.
@menu @menu
* Missing Sub-selects:: Sub-selects * Missing Sub-selects:: Sub-selects
...@@ -12726,8 +12728,8 @@ Database, table, index, column, and alias names all follow the same rules in ...@@ -12726,8 +12728,8 @@ Database, table, index, column, and alias names all follow the same rules in
@tindex " @tindex "
Note that the rules changed starting with @strong{MySQL} Version 3.23.6 when we Note that the rules changed starting with @strong{MySQL} Version 3.23.6 when we
introduced quoting of identifiers (database, table, and column names) introduced quoting of identifiers (database, table, and column names)
with @samp{`} (@samp{"} will also work to quote identifiers if you run with @samp{`}. @samp{"} will also work to quote identifiers if you run
in ANSI mode). in ANSI mode. @xref{ANSI mode}.
@multitable @columnfractions .15 .15 .70 @multitable @columnfractions .15 .15 .70
@item @strong{Identifier} @tab @strong{Max length} @tab @strong{Allowed characters} @item @strong{Identifier} @tab @strong{Max length} @tab @strong{Allowed characters}
...@@ -13405,7 +13407,7 @@ standard, @strong{MySQL} recognizes @code{DOUBLE} as a synonym for the ...@@ -13405,7 +13407,7 @@ standard, @strong{MySQL} recognizes @code{DOUBLE} as a synonym for the
@code{DOUBLE PRECISION} type. In contrast with the standard's @code{DOUBLE PRECISION} type. In contrast with the standard's
requirement that the precision for @code{REAL} be smaller than that used requirement that the precision for @code{REAL} be smaller than that used
for @code{DOUBLE PRECISION}, @strong{MySQL} implements both as 8-byte for @code{DOUBLE PRECISION}, @strong{MySQL} implements both as 8-byte
double-precision floating-point values (when not running in ``Ansi mode''). double-precision floating-point values (when not running in ``ANSI mode'').
For maximum portability, code requiring storage of approximate numeric For maximum portability, code requiring storage of approximate numeric
data values should use @code{FLOAT} or @code{DOUBLE PRECISION} with no data values should use @code{FLOAT} or @code{DOUBLE PRECISION} with no
specification of precision or number of decimal points. specification of precision or number of decimal points.
...@@ -17838,7 +17840,9 @@ running! ...@@ -17838,7 +17840,9 @@ running!
@section @code{CHECK TABLE} Syntax @section @code{CHECK TABLE} Syntax
@example @example
CHECK TABLE tbl_name[,tbl_name...] [TYPE = [QUICK | FAST | EXTEND | CHANGED]] CHECK TABLE tbl_name[,tbl_name...] [option [option...]]
option = QUICK | FAST | EXTEND | CHANGED
@end example @end example
@code{CHECK TABLE} only works on @code{MyISAM} tables and is the same thing @code{CHECK TABLE} only works on @code{MyISAM} tables and is the same thing
...@@ -17872,6 +17876,14 @@ The different check types stand for the following: ...@@ -17872,6 +17876,14 @@ The different check types stand for the following:
@item @code{EXTENDED} @tab Do a full key lookup for all keys for each row. This ensures that the table is 100 % consistent, but will take a long time! @item @code{EXTENDED} @tab Do a full key lookup for all keys for each row. This ensures that the table is 100 % consistent, but will take a long time!
@end multitable @end multitable
You can combine check options as in:
@example
CHECK TABLE test_table FAST QUICK;
@end example
Which only would do a quick check on the table if it wasn't closed properly.
If a table is corrupted, then it's most likely that the problem is in If a table is corrupted, then it's most likely that the problem is in
the indexes and not in the data part. All of the above check types the indexes and not in the data part. All of the above check types
checks the indexes throughly and should thus find most errors. checks the indexes throughly and should thus find most errors.
...@@ -17881,7 +17893,8 @@ no check options or the @code{QUICK} option. The later should be used ...@@ -17881,7 +17893,8 @@ no check options or the @code{QUICK} option. The later should be used
when you are in a hurry and can take the very small risk that when you are in a hurry and can take the very small risk that
@code{QUICK} didn't find an error in the data file (In most cases @code{QUICK} didn't find an error in the data file (In most cases
@strong{MySQL} should find, under normal usage, any error in the data @strong{MySQL} should find, under normal usage, any error in the data
file. If this happens then the table will be marked as 'corrupted'. file. If this happens then the table will be marked as 'corrupted',
in which case the table can't be used until it's repaired).
@code{FAST} and @code{CHANGED} are mostly intended to be used from a @code{FAST} and @code{CHANGED} are mostly intended to be used from a
script (for example to be executed from cron) if you want to check your script (for example to be executed from cron) if you want to check your
...@@ -17988,7 +18001,7 @@ the table will not be analyzed again. ...@@ -17988,7 +18001,7 @@ the table will not be analyzed again.
@section @code{REPAIR TABLE} syntax @section @code{REPAIR TABLE} syntax
@example @example
REPAIR TABLE tbl_name[,tbl_name...] [TYPE = QUICK] REPAIR TABLE tbl_name[,tbl_name...] [QUICK]
@end example @end example
@code{REPAIR TABLE} only works on @code{MyISAM} tables and is the same things @code{REPAIR TABLE} only works on @code{MyISAM} tables and is the same things
...@@ -18012,7 +18025,7 @@ repairing the table with @code{myisamchk -o}, as @code{REPAIR TABLE} ...@@ -18012,7 +18025,7 @@ repairing the table with @code{myisamchk -o}, as @code{REPAIR TABLE}
does not yet implement all the options of @code{myisamchk}. In the near does not yet implement all the options of @code{myisamchk}. In the near
future, we will make it more flexible. future, we will make it more flexible.
If @code{TYPE=QUICK} is given then @strong{MySQL} will try to do a If @code{QUICK} is given then @strong{MySQL} will try to do a
@code{REPAIR} of only the index tree. @code{REPAIR} of only the index tree.
@findex DELETE @findex DELETE
...@@ -19692,7 +19705,7 @@ indicates 16 megabytes. The case of suffix letters does not matter; ...@@ -19692,7 +19705,7 @@ indicates 16 megabytes. The case of suffix letters does not matter;
@table @code @table @code
@item @code{ansi_mode}. @item @code{ansi_mode}.
Is @code{ON} if @code{mysqld} was started with @code{--ansi}. Is @code{ON} if @code{mysqld} was started with @code{--ansi}.
@xref{Ansi mode}. @xref{ANSI mode}.
@item @code{back_log} @item @code{back_log}
The number of outstanding connection requests @strong{MySQL} can have. This The number of outstanding connection requests @strong{MySQL} can have. This
...@@ -37858,6 +37871,13 @@ though, so 3.23 is not released as a stable version yet. ...@@ -37858,6 +37871,13 @@ 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
Automatic repair of @code{MyISAM} tables if you start @code{mysqld} with
@code{--myisam-recover}.
@item
Removed the @code{TYPE=} keyword from @code{CHECK} and
@code{REPAIR}. Allow one to combine @code{CHECK} options. (One can still
use @code{TYPE=} but this usage is deprecated).
@item
Added optimization of queries where @code{DISTINCT} is only used on columns Added optimization of queries where @code{DISTINCT} is only used on columns
from some of the tables. from some of the tables.
@item @item
...@@ -46,6 +46,7 @@ ...@@ -46,6 +46,7 @@
#define HA_OPEN_TMP_TABLE 4 /* Table is a temp table */ #define HA_OPEN_TMP_TABLE 4 /* Table is a temp table */
#define HA_OPEN_DELAY_KEY_WRITE 8 /* Don't update index */ #define HA_OPEN_DELAY_KEY_WRITE 8 /* Don't update index */
#define HA_OPEN_ABORT_IF_CRASHED 16 #define HA_OPEN_ABORT_IF_CRASHED 16
#define HA_OPEN_FOR_REPAIR 32 /* open even if crashed */
/* The following is parameter to ha_rkey() how to use key */ /* The following is parameter to ha_rkey() how to use key */
......
...@@ -308,22 +308,23 @@ typedef struct st_sort_info { ...@@ -308,22 +308,23 @@ typedef struct st_sort_info {
typedef struct st_mi_check_param typedef struct st_mi_check_param
{ {
ulonglong auto_increment_value;
ulonglong max_data_file_length;
ulonglong keys_in_use;
my_off_t search_after_block;
my_off_t new_file_pos,key_file_blocks;
my_off_t keydata,totaldata,key_blocks,start_check_pos;
ha_rows total_records,total_deleted;
ha_checksum record_checksum,glob_crc;
ulong use_buffers,read_buffer_length,write_buffer_length, ulong use_buffers,read_buffer_length,write_buffer_length,
sort_buffer_length,sort_key_blocks; sort_buffer_length,sort_key_blocks;
uint out_flag,warning_printed,error_printed, uint out_flag,warning_printed,error_printed,
opt_rep_quick,verbose; opt_rep_quick,verbose;
uint opt_sort_key,total_files,max_level; uint opt_sort_key,total_files,max_level;
uint testflag;
uint8 language; uint8 language;
my_bool using_global_keycache, opt_lock_memory, opt_follow_links; my_bool using_global_keycache, opt_lock_memory, opt_follow_links;
uint testflag; my_bool retry_repair,retry_without_quick;
ha_rows total_records,total_deleted;
ulonglong auto_increment_value;
my_off_t search_after_block;
ulonglong max_data_file_length;
ulonglong keys_in_use;
my_off_t new_file_pos,key_file_blocks;
my_off_t keydata,totaldata,key_blocks,start_check_pos;
ha_checksum record_checksum,glob_crc;
char temp_filename[FN_REFLEN],*isam_file_name,*tmpdir; char temp_filename[FN_REFLEN],*isam_file_name,*tmpdir;
int tmpfile_createflag; int tmpfile_createflag;
myf myf_rw; myf myf_rw;
......
...@@ -64,7 +64,7 @@ static FT_WORD * _mi_ft_parserecord(MI_INFO *info, uint keynr, byte *keybuf, ...@@ -64,7 +64,7 @@ static FT_WORD * _mi_ft_parserecord(MI_INFO *info, uint keynr, byte *keybuf,
return NULL; return NULL;
} }
/* Handle the case where all columns are NULL */ /* Handle the case where all columns are NULL */
if (!parsed && !(parsed=ft_parse(0, "", 0))) if (!parsed && !(parsed=ft_parse(0, (byte*) "", 0)))
return NULL; return NULL;
return ft_linearize(info, keynr, keybuf, parsed); return ft_linearize(info, keynr, keybuf, parsed);
} }
......
...@@ -192,6 +192,7 @@ int chk_del(MI_CHECK *param, register MI_INFO *info, uint test_flag) ...@@ -192,6 +192,7 @@ int chk_del(MI_CHECK *param, register MI_INFO *info, uint test_flag)
} }
DBUG_RETURN(0); DBUG_RETURN(0);
wrong: wrong:
param->retry_without_quick=1; // Don't use quick repair
if (test_flag & T_VERBOSE) puts(""); if (test_flag & T_VERBOSE) puts("");
mi_check_print_error(param,"record delete-link-chain corrupted"); mi_check_print_error(param,"record delete-link-chain corrupted");
DBUG_RETURN(1); DBUG_RETURN(1);
...@@ -291,6 +292,7 @@ int chk_size(MI_CHECK *param, register MI_INFO *info) ...@@ -291,6 +292,7 @@ int chk_size(MI_CHECK *param, register MI_INFO *info)
error=1; error=1;
mi_check_print_error(param,"Size of datafile is: %-8s Should be: %s", mi_check_print_error(param,"Size of datafile is: %-8s Should be: %s",
llstr(size,buff), llstr(skr,buff2)); llstr(size,buff), llstr(skr,buff2));
param->retry_without_quick=1; // Don't use quick repair
} }
else else
{ {
...@@ -750,8 +752,9 @@ int chk_data_link(MI_CHECK *param, MI_INFO *info,int extend) ...@@ -750,8 +752,9 @@ int chk_data_link(MI_CHECK *param, MI_INFO *info,int extend)
{ {
if (block_info.block_len < info->s->base.min_block_length) if (block_info.block_len < info->s->base.min_block_length)
{ {
mi_check_print_error(param,"Deleted block with impossible length %lu at %s", mi_check_print_error(param,
block_info.block_len,llstr(pos,llbuff)); "Deleted block with impossible length %lu at %s",
block_info.block_len,llstr(pos,llbuff));
goto err2; goto err2;
} }
if ((block_info.next_filepos != HA_OFFSET_ERROR && if ((block_info.next_filepos != HA_OFFSET_ERROR &&
...@@ -1071,7 +1074,7 @@ int mi_repair(MI_CHECK *param, register MI_INFO *info, ...@@ -1071,7 +1074,7 @@ int mi_repair(MI_CHECK *param, register MI_INFO *info,
new_file= -1; new_file= -1;
if (!(param->testflag & T_SILENT)) if (!(param->testflag & T_SILENT))
{ {
printf("- recovering MyISAM-table '%s'\n",name); printf("- recovering (with keycache) MyISAM-table '%s'\n",name);
printf("Data records: %s\n", llstr(info->state->records,llbuff)); printf("Data records: %s\n", llstr(info->state->records,llbuff));
} }
...@@ -1211,6 +1214,7 @@ int mi_repair(MI_CHECK *param, register MI_INFO *info, ...@@ -1211,6 +1214,7 @@ int mi_repair(MI_CHECK *param, register MI_INFO *info,
mi_check_print_error(param,"Couldn't fix table with quick recovery: Found wrong number of deleted records"); mi_check_print_error(param,"Couldn't fix table with quick recovery: Found wrong number of deleted records");
mi_check_print_error(param,"Run recovery again without -q"); mi_check_print_error(param,"Run recovery again without -q");
got_error=1; got_error=1;
param->retry_repair=param->retry_without_quick=1;
goto err; goto err;
} }
...@@ -1651,7 +1655,7 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info, ...@@ -1651,7 +1655,7 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info,
share->pack.header_length; share->pack.header_length;
if (!(param->testflag & T_SILENT)) if (!(param->testflag & T_SILENT))
{ {
printf("- recovering MyISAM-table '%s'\n",name); printf("- recovering (with sort) MyISAM-table '%s'\n",name);
printf("Data records: %s\n", llstr(start_records,llbuff)); printf("Data records: %s\n", llstr(start_records,llbuff));
} }
bzero((char*) sort_info,sizeof(*sort_info)); bzero((char*) sort_info,sizeof(*sort_info));
...@@ -1805,7 +1809,10 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info, ...@@ -1805,7 +1809,10 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info,
if (_create_index_by_sort(&sort_param, if (_create_index_by_sort(&sort_param,
(my_bool) (!(param->testflag & T_VERBOSE)), (my_bool) (!(param->testflag & T_VERBOSE)),
(uint) param->sort_buffer_length)) (uint) param->sort_buffer_length))
{
param->retry_repair=1;
goto err; goto err;
}
/* Set for next loop */ /* Set for next loop */
sort_param.max_records=sort_info->max_records= sort_param.max_records=sort_info->max_records=
...@@ -1862,6 +1869,7 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info, ...@@ -1862,6 +1869,7 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info,
mi_check_print_error(param,"Couldn't fix table with quick recovery: Found wrong number of deleted records"); mi_check_print_error(param,"Couldn't fix table with quick recovery: Found wrong number of deleted records");
mi_check_print_error(param,"Run recovery again without -q"); mi_check_print_error(param,"Run recovery again without -q");
got_error=1; got_error=1;
param->retry_repair=param->retry_without_quick=1;
goto err; goto err;
} }
...@@ -3037,7 +3045,8 @@ void mi_disable_non_unique_index(MI_INFO *info, ha_rows rows) ...@@ -3037,7 +3045,8 @@ void mi_disable_non_unique_index(MI_INFO *info, ha_rows rows)
even if the temporary file would be quite big! even if the temporary file would be quite big!
*/ */
my_bool mi_test_if_sort_rep(MI_INFO *info, ha_rows rows, my_bool force) my_bool mi_test_if_sort_rep(MI_INFO *info, ha_rows rows,
my_bool force __attribute__((unused)))
{ {
MYISAM_SHARE *share=info->s; MYISAM_SHARE *share=info->s;
uint i; uint i;
......
...@@ -174,9 +174,10 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags) ...@@ -174,9 +174,10 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
disk_pos=my_n_base_info_read(disk_cache+base_pos, &share->base); disk_pos=my_n_base_info_read(disk_cache+base_pos, &share->base);
share->state.state_length=base_pos; share->state.state_length=base_pos;
if ((open_flags & HA_OPEN_ABORT_IF_CRASHED) && if (!(open_flags & HA_OPEN_FOR_REPAIR) &&
((share->state.changed & STATE_CRASHED) || ((share->state.changed & STATE_CRASHED) ||
(my_disable_locking && share->state.open_count))) ((open_flags & HA_OPEN_ABORT_IF_CRASHED) &&
(my_disable_locking && share->state.open_count))))
{ {
DBUG_PRINT("error",("Table is marked as crashed")); DBUG_PRINT("error",("Table is marked as crashed"));
my_errno=((share->state.changed & STATE_CRASHED_ON_REPAIR) ? my_errno=((share->state.changed & STATE_CRASHED_ON_REPAIR) ?
......
...@@ -92,7 +92,7 @@ int main(int argc, char **argv) ...@@ -92,7 +92,7 @@ int main(int argc, char **argv)
error=0; error=0;
while (--argc >= 0) while (--argc >= 0)
{ {
error|= myisamchk(&check_param, *(argv++)); int new_error=myisamchk(&check_param, *(argv++));
VOID(fflush(stdout)); VOID(fflush(stdout));
VOID(fflush(stderr)); VOID(fflush(stderr));
if ((check_param.error_printed | check_param.warning_printed) && if ((check_param.error_printed | check_param.warning_printed) &&
...@@ -101,13 +101,16 @@ int main(int argc, char **argv) ...@@ -101,13 +101,16 @@ int main(int argc, char **argv)
T_SORT_INDEX)))) T_SORT_INDEX))))
{ {
uint old_testflag=check_param.testflag; uint old_testflag=check_param.testflag;
check_param.testflag|=T_REP; if (!(check_param.testflag & T_REP))
check_param.testflag|= T_REP_BY_SORT;
check_param.testflag&= ~T_EXTEND; /* Don't needed */ check_param.testflag&= ~T_EXTEND; /* Don't needed */
error|=myisamchk(&check_param, argv[-1]); error|=myisamchk(&check_param, argv[-1]);
check_param.testflag= old_testflag; check_param.testflag= old_testflag;
VOID(fflush(stdout)); VOID(fflush(stdout));
VOID(fflush(stderr)); VOID(fflush(stderr));
} }
else
error|=new_error;
if (argc && (!(check_param.testflag & T_SILENT) || check_param.testflag & T_INFO)) if (argc && (!(check_param.testflag & T_SILENT) || check_param.testflag & T_INFO))
{ {
puts("\n---------\n"); puts("\n---------\n");
...@@ -193,7 +196,7 @@ static struct option long_options[] = ...@@ -193,7 +196,7 @@ static struct option long_options[] =
static void print_version(void) static void print_version(void)
{ {
printf("%s Ver 1.32 for %s at %s\n",my_progname,SYSTEM_TYPE, printf("%s Ver 1.34 for %s at %s\n",my_progname,SYSTEM_TYPE,
MACHINE_TYPE); MACHINE_TYPE);
} }
...@@ -229,7 +232,7 @@ static void usage(void) ...@@ -229,7 +232,7 @@ static void usage(void)
-f, --force Restart with -r if there are any errors in the table\n\ -f, --force Restart with -r if there are any errors in the table\n\
-i, --information Print statistics information about table that is checked\n\ -i, --information Print statistics information about table that is checked\n\
-m, --medium-check Faster than extended-check, but only finds 99.99% of\n\ -m, --medium-check Faster than extended-check, but only finds 99.99% of\n\
all errors. Should however be good enough for most cases\n\ all errors. Should be good enough for most cases\n\
-U --update-state Mark tables as crashed if you find any errors\n\ -U --update-state Mark tables as crashed if you find any errors\n\
-T, --read-only Don't mark table as checked\n"); -T, --read-only Don't mark table as checked\n");
...@@ -488,10 +491,11 @@ static int myisamchk(MI_CHECK *param, my_string filename) ...@@ -488,10 +491,11 @@ static int myisamchk(MI_CHECK *param, my_string filename)
if (!(info=mi_open(filename, if (!(info=mi_open(filename,
(param->testflag & (T_DESCRIPT | T_READONLY)) ? (param->testflag & (T_DESCRIPT | T_READONLY)) ?
O_RDONLY : O_RDWR, O_RDONLY : O_RDWR,
(param->testflag & T_WAIT_FOREVER) ? HA_OPEN_FOR_REPAIR |
HA_OPEN_WAIT_IF_LOCKED : ((param->testflag & T_WAIT_FOREVER) ?
(param->testflag & T_DESCRIPT) ? HA_OPEN_WAIT_IF_LOCKED :
HA_OPEN_IGNORE_IF_LOCKED : HA_OPEN_ABORT_IF_LOCKED))) (param->testflag & T_DESCRIPT) ?
HA_OPEN_IGNORE_IF_LOCKED : HA_OPEN_ABORT_IF_LOCKED))))
{ {
/* Avoid twice printing of isam file name */ /* Avoid twice printing of isam file name */
param->error_printed=1; param->error_printed=1;
...@@ -748,8 +752,8 @@ static int myisamchk(MI_CHECK *param, my_string filename) ...@@ -748,8 +752,8 @@ static int myisamchk(MI_CHECK *param, my_string filename)
error =chk_size(param,info); error =chk_size(param,info);
if (!error || !(param->testflag & (T_FAST | T_FORCE_CREATE))) if (!error || !(param->testflag & (T_FAST | T_FORCE_CREATE)))
error|=chk_del(param, info,param->testflag); error|=chk_del(param, info,param->testflag);
if ((!error || !(param->testflag & (T_FAST | T_FORCE_CREATE)) && if ((!error || (!(param->testflag & (T_FAST | T_FORCE_CREATE)) &&
!param->start_check_pos)) !param->start_check_pos)))
{ {
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)))
......
...@@ -155,10 +155,10 @@ int _create_index_by_sort(MI_SORT_PARAM *info,my_bool no_messages, ...@@ -155,10 +155,10 @@ int _create_index_by_sort(MI_SORT_PARAM *info,my_bool no_messages,
printf(" - Merging %lu keys\n",records); printf(" - Merging %lu keys\n",records);
if (merge_many_buff(info,keys,sort_keys,buffpek,&maxbuffer,&tempfile)) if (merge_many_buff(info,keys,sort_keys,buffpek,&maxbuffer,&tempfile))
goto err; goto err;
if (flush_io_cache(&tempfile) ||
reinit_io_cache(&tempfile,READ_CACHE,0L,0,0))
goto err;
} }
if (flush_io_cache(&tempfile) ||
reinit_io_cache(&tempfile,READ_CACHE,0L,0,0))
goto err;
if (!no_messages) if (!no_messages)
puts(" - Last merge and dumping keys"); puts(" - Last merge and dumping keys");
if (merge_index(info,keys,sort_keys,buffpek,maxbuffer,&tempfile)) if (merge_index(info,keys,sort_keys,buffpek,maxbuffer,&tempfile))
......
...@@ -67,7 +67,7 @@ static char *name_from_csnum(CS_ID **cs, uint number) ...@@ -67,7 +67,7 @@ static char *name_from_csnum(CS_ID **cs, uint number)
for (c = cs; *c; ++c) for (c = cs; *c; ++c)
if ((*c)->number == number) if ((*c)->number == number)
return (*c)->name; return (*c)->name;
return "?"; /* this mimics find_type() */ return (char*) "?"; /* this mimics find_type() */
} }
static my_bool get_word(struct simpleconfig_buf_st *fb, char *buf) static my_bool get_word(struct simpleconfig_buf_st *fb, char *buf)
...@@ -487,7 +487,7 @@ char * list_charsets(myf want_flags) ...@@ -487,7 +487,7 @@ char * list_charsets(myf want_flags)
{ {
CS_ID **c; CS_ID **c;
char buf[FN_REFLEN]; char buf[FN_REFLEN];
MY_STAT stat; MY_STAT status;
if((c=available_charsets)) if((c=available_charsets))
for (; *c; ++c) for (; *c; ++c)
...@@ -495,7 +495,7 @@ char * list_charsets(myf want_flags) ...@@ -495,7 +495,7 @@ char * list_charsets(myf want_flags)
if (charset_in_string((*c)->name, &s)) if (charset_in_string((*c)->name, &s))
continue; continue;
get_charset_conf_name((*c)->number, buf); get_charset_conf_name((*c)->number, buf);
if (!my_stat(buf, &stat, MYF(0))) if (!my_stat(buf, &status, MYF(0)))
continue; /* conf file doesn't exist */ continue; /* conf file doesn't exist */
dynstr_append(&s, (*c)->name); dynstr_append(&s, (*c)->name);
dynstr_append(&s, " "); dynstr_append(&s, " ");
......
...@@ -148,7 +148,7 @@ void load_defaults(const char *conf_file, const char **groups, ...@@ -148,7 +148,7 @@ void load_defaults(const char *conf_file, const char **groups,
#endif #endif
for (dirs=default_directories ; *dirs; dirs++) for (dirs=default_directories ; *dirs; dirs++)
{ {
int error; int error=0;
if (**dirs) if (**dirs)
error=search_default_file(&args, &alloc, *dirs, conf_file, error=search_default_file(&args, &alloc, *dirs, conf_file,
default_ext, &group); default_ext, &group);
...@@ -359,7 +359,12 @@ void print_defaults(const char *conf_file, const char **groups) ...@@ -359,7 +359,12 @@ void print_defaults(const char *conf_file, const char **groups)
#endif #endif
for (dirs=default_directories ; *dirs; dirs++) for (dirs=default_directories ; *dirs; dirs++)
{ {
strmov(name,*dirs); if (**dirs)
strmov(name,*dirs);
else if (defaults_extra_file)
strmov(name,defaults_extra_file);
else
continue;
convert_dirname(name); convert_dirname(name);
if (name[0] == FN_HOMELIB) /* Add . to filenames in home */ if (name[0] == FN_HOMELIB) /* Add . to filenames in home */
strcat(name,"."); strcat(name,".");
...@@ -377,6 +382,7 @@ void print_defaults(const char *conf_file, const char **groups) ...@@ -377,6 +382,7 @@ void print_defaults(const char *conf_file, const char **groups)
puts("\nThe following options may be given as the first argument:\n\ puts("\nThe following options may be given as the first argument:\n\
--print-defaults Print the program argument list and exit\n\ --print-defaults Print the program argument list and exit\n\
--no-defaults Don't read default options from any options file\n\ --no-defaults Don't read default options from any options file\n\
--defaults-file=# Only read default options from the given file #"); --defaults-file=# Only read default options from the given file #\n\
--defaults-extra-file=# Read this file after the global files are read");
} }
...@@ -36,7 +36,8 @@ extern char **environ; ...@@ -36,7 +36,8 @@ extern char **environ;
*/ */
File create_temp_file(char *to, const char *dir, const char *prefix, File create_temp_file(char *to, const char *dir, const char *prefix,
int mode, myf MyFlags) int mode __attribute__((unused)),
myf MyFlags __attribute__((unused)))
{ {
File file= -1; File file= -1;
DBUG_ENTER("open_temp_file"); DBUG_ENTER("open_temp_file");
...@@ -85,12 +86,12 @@ File create_temp_file(char *to, const char *dir, const char *prefix, ...@@ -85,12 +86,12 @@ File create_temp_file(char *to, const char *dir, const char *prefix,
} }
#elif defined(HAVE_MKSTEMP) #elif defined(HAVE_MKSTEMP)
{ {
char prefix[30]; char prefix_buff[30];
uint pfx_len; uint pfx_len;
pfx_len=(strmov(strnmov(prefix, pfx_len=(strmov(strnmov(prefix_buff,
prefix ? prefix : "tmp.", prefix ? prefix : "tmp.",
sizeof(prefix)-7),"XXXXXX") - prefix); sizeof(prefix_buff)-7),"XXXXXX") - prefix_buff);
if (!dir && ! (dir =getenv("TMPDIR"))) if (!dir && ! (dir =getenv("TMPDIR")))
dir=P_tmpdir; dir=P_tmpdir;
if (strlen(dir)+ pfx_len > FN_REFLEN-2) if (strlen(dir)+ pfx_len > FN_REFLEN-2)
......
...@@ -48,7 +48,7 @@ static my_bool win32_init_tcp_ip(); ...@@ -48,7 +48,7 @@ static my_bool win32_init_tcp_ip();
static my_bool my_init_done=0; static my_bool my_init_done=0;
ulong atoi_octal(const char *str) static ulong atoi_octal(const char *str)
{ {
long int tmp; long int tmp;
while (*str && isspace(*str)) while (*str && isspace(*str))
......
...@@ -80,7 +80,6 @@ uint my_pread(File Filedes, byte *Buffer, uint Count, my_off_t offset, ...@@ -80,7 +80,6 @@ uint my_pread(File Filedes, byte *Buffer, uint Count, my_off_t offset,
uint my_pwrite(int Filedes, const byte *Buffer, uint Count, my_off_t offset, uint my_pwrite(int Filedes, const byte *Buffer, uint Count, my_off_t offset,
myf MyFlags) myf MyFlags)
{ {
int error;
uint writenbytes,errors; uint writenbytes,errors;
ulong written; ulong written;
DBUG_ENTER("my_pwrite"); DBUG_ENTER("my_pwrite");
...@@ -91,6 +90,7 @@ uint my_pwrite(int Filedes, const byte *Buffer, uint Count, my_off_t offset, ...@@ -91,6 +90,7 @@ uint my_pwrite(int Filedes, const byte *Buffer, uint Count, my_off_t offset,
for (;;) for (;;)
{ {
#ifndef HAVE_PREAD #ifndef HAVE_PREAD
int error;
writenbytes= (uint) -1; writenbytes= (uint) -1;
pthread_mutex_lock(&my_file_info[Filedes].mutex); pthread_mutex_lock(&my_file_info[Filedes].mutex);
error=(lseek(Filedes, offset, MY_SEEK_SET) != -1L && error=(lseek(Filedes, offset, MY_SEEK_SET) != -1L &&
......
...@@ -161,6 +161,7 @@ sub new ...@@ -161,6 +161,7 @@ sub new
$limits{'func_extra_in_num'} = 1; # Has function in $limits{'func_extra_in_num'} = 1; # Has function in
$limits{'limit'} = 1; # supports the limit attribute $limits{'limit'} = 1; # supports the limit attribute
$limits{'unique_index'} = 1; # Unique index works or not $limits{'unique_index'} = 1; # Unique index works or not
$limits{'insert_select'} = 1;
$smds{'time'} = 1; $smds{'time'} = 1;
$smds{'q1'} = 'b'; # with time not supp by mysql ('') $smds{'q1'} = 'b'; # with time not supp by mysql ('')
...@@ -378,6 +379,7 @@ sub new ...@@ -378,6 +379,7 @@ sub new
$limits{'group_func_extra_std'} = 0; $limits{'group_func_extra_std'} = 0;
$limits{'limit'} = 1; # supports the limit attribute $limits{'limit'} = 1; # supports the limit attribute
$limits{'unique_index'} = 1; # Unique index works or not $limits{'unique_index'} = 1; # Unique index works or not
$limits{'insert_select'} = 0;
$limits{'func_odbc_mod'} = 0; $limits{'func_odbc_mod'} = 0;
$limits{'func_extra_%'} = 0; $limits{'func_extra_%'} = 0;
...@@ -576,6 +578,7 @@ sub new ...@@ -576,6 +578,7 @@ sub new
$limits{'max_text_size'} = 7000; # 8000 crashes pg 6.3 $limits{'max_text_size'} = 7000; # 8000 crashes pg 6.3
$limits{'query_size'} = 16777216; $limits{'query_size'} = 16777216;
$limits{'unique_index'} = 1; # Unique index works or not $limits{'unique_index'} = 1; # Unique index works or not
$limits{'insert_select'} = 1;
# the different cases per query ... # the different cases per query ...
$smds{'q1'} = 'b'; # with time $smds{'q1'} = 'b'; # with time
...@@ -849,6 +852,7 @@ sub new ...@@ -849,6 +852,7 @@ sub new
$limits{'NEG'} = 1; $limits{'NEG'} = 1;
$limits{'func_extra_in_num'} = 1; $limits{'func_extra_in_num'} = 1;
$limits{'unique_index'} = 1; # Unique index works or not $limits{'unique_index'} = 1; # Unique index works or not
$limits{'insert_select'} = 1;
# for the smds small benchmark test .... # for the smds small benchmark test ....
# the different cases per query ... # the different cases per query ...
...@@ -1087,6 +1091,7 @@ sub new ...@@ -1087,6 +1091,7 @@ sub new
$limits{'NEG'} = 1; $limits{'NEG'} = 1;
$limits{'func_extra_in_num'} = 0; $limits{'func_extra_in_num'} = 0;
$limits{'unique_index'} = 1; # Unique index works or not $limits{'unique_index'} = 1; # Unique index works or not
$limits{'insert_select'} = 1;
# for the smds small benchmark test .... # for the smds small benchmark test ....
# the different cases per query ... EMPRESS # the different cases per query ... EMPRESS
...@@ -1364,6 +1369,7 @@ sub new ...@@ -1364,6 +1369,7 @@ sub new
$limits{'NEG'} = 1; # Supports -id $limits{'NEG'} = 1; # Supports -id
$limits{'func_extra_in_num'} = 1; # Has function in $limits{'func_extra_in_num'} = 1; # Has function in
$limits{'unique_index'} = 1; # Unique index works or not $limits{'unique_index'} = 1; # Unique index works or not
$limits{'insert_select'} = 1;
$smds{'time'} = 1; $smds{'time'} = 1;
$smds{'q1'} = 'b'; # with time not supp by mysql ('') $smds{'q1'} = 'b'; # with time not supp by mysql ('')
...@@ -1612,6 +1618,7 @@ sub new ...@@ -1612,6 +1618,7 @@ sub new
$limits{'subqueries'} = 1; # Doesn't support sub-queries. $limits{'subqueries'} = 1; # Doesn't support sub-queries.
$limits{'table_wildcard'} = 1; # Has SELECT table_name.* $limits{'table_wildcard'} = 1; # Has SELECT table_name.*
$limits{'unique_index'} = 1; # Unique index works or not $limits{'unique_index'} = 1; # Unique index works or not
$limits{'insert_select'} = 1;
return $self; return $self;
} }
...@@ -1809,6 +1816,7 @@ sub new ...@@ -1809,6 +1816,7 @@ sub new
$limits{'NEG'} = 1; # Supports -id $limits{'NEG'} = 1; # Supports -id
$limits{'func_extra_in_num'} = 1; # Has function in $limits{'func_extra_in_num'} = 1; # Has function in
$limits{'unique_index'} = 1; # Unique index works or not $limits{'unique_index'} = 1; # Unique index works or not
$limits{'insert_select'} = 1;
return $self; return $self;
} }
...@@ -1980,6 +1988,7 @@ sub new ...@@ -1980,6 +1988,7 @@ sub new
$limits{'NEG'} = 1; # Supports -id $limits{'NEG'} = 1; # Supports -id
$limits{'func_extra_in_num'} = 0; # Has function in $limits{'func_extra_in_num'} = 0; # Has function in
$limits{'unique_index'} = 1; # Unique index works or not $limits{'unique_index'} = 1; # Unique index works or not
$limits{'insert_select'} = 1;
return $self; return $self;
} }
...@@ -2163,6 +2172,7 @@ sub new ...@@ -2163,6 +2172,7 @@ sub new
$limits{'NEG'} = 1; # Supports -id $limits{'NEG'} = 1; # Supports -id
$limits{'func_extra_in_num'} = 0; # Has function in $limits{'func_extra_in_num'} = 0; # Has function in
$limits{'unique_index'} = 1; # Unique index works or not $limits{'unique_index'} = 1; # Unique index works or not
$limits{'insert_select'} = 1;
return $self; return $self;
} }
...@@ -2349,6 +2359,7 @@ sub new ...@@ -2349,6 +2359,7 @@ sub new
$limits{'NEG'} = 1; # Supports -id $limits{'NEG'} = 1; # Supports -id
$limits{'func_extra_in_num'} = 1; # Has function in $limits{'func_extra_in_num'} = 1; # Has function in
$limits{'unique_index'} = 1; # Unique index works or not $limits{'unique_index'} = 1; # Unique index works or not
$limits{'insert_select'} = 1;
$smds{'time'} = 1; $smds{'time'} = 1;
$smds{'q1'} = 'b'; # with time not supp by mysql ('') $smds{'q1'} = 'b'; # with time not supp by mysql ('')
...@@ -2558,6 +2569,7 @@ sub new ...@@ -2558,6 +2569,7 @@ sub new
$limits{'NEG'} = 1; # Supports -id $limits{'NEG'} = 1; # Supports -id
$limits{'func_extra_in_num'} = 0; # Has function in $limits{'func_extra_in_num'} = 0; # Has function in
$limits{'unique_index'} = 1; # Unique index works or not $limits{'unique_index'} = 1; # Unique index works or not
$limits{'insert_select'} = 1;
return $self; return $self;
} }
...@@ -2726,6 +2738,7 @@ sub new ...@@ -2726,6 +2738,7 @@ sub new
$limits{'func_extra_in_num'} = 1; # Has function in $limits{'func_extra_in_num'} = 1; # Has function in
$limits{'limit'} = 0; # Does not support the limit attribute $limits{'limit'} = 0; # Does not support the limit attribute
$limits{'unique_index'} = 1; # Unique index works or not $limits{'unique_index'} = 1; # Unique index works or not
$limits{'insert_select'} = 1;
$smds{'time'} = 1; $smds{'time'} = 1;
$smds{'q1'} = 'b'; # with time not supp by mysql ('') $smds{'q1'} = 'b'; # with time not supp by mysql ('')
......
...@@ -97,6 +97,8 @@ goto select_test if ($opt_skip_create); ...@@ -97,6 +97,8 @@ goto select_test if ($opt_skip_create);
print "Creating tables\n"; print "Creating tables\n";
$dbh->do("drop table bench1"); $dbh->do("drop table bench1");
$dbh->do("drop table bench2");
$dbh->do("drop table bench3");
do_many($dbh,$server->create("bench1", do_many($dbh,$server->create("bench1",
["id int NOT NULL", ["id int NOT NULL",
"id2 int NOT NULL", "id2 int NOT NULL",
...@@ -240,7 +242,7 @@ if ($limits->{'unique_index'}) ...@@ -240,7 +242,7 @@ if ($limits->{'unique_index'})
} }
$end_time=new Benchmark; $end_time=new Benchmark;
print "Time for insert_duplicates (" . ($total_rows) . "): " . print "Time for insert_duplicates (" . ($opt_loop_count) . "): " .
timestr(timediff($end_time, $loop_time),"all") . "\n\n"; timestr(timediff($end_time, $loop_time),"all") . "\n\n";
#if ($opt_fast && defined($server->{vacuum})) #if ($opt_fast && defined($server->{vacuum}))
...@@ -611,7 +613,7 @@ if ($limits->{'functions'}) ...@@ -611,7 +613,7 @@ if ($limits->{'functions'})
} }
$end_time=new Benchmark; $end_time=new Benchmark;
print "Time for update_of_key ($range_loop_count): " . print "Time for update_of_key ($update_loop_count): " .
timestr(timediff($end_time, $loop_time),"all") . "\n"; timestr(timediff($end_time, $loop_time),"all") . "\n";
if ($opt_lock_tables) if ($opt_lock_tables)
...@@ -775,7 +777,7 @@ for ($i=0 ; $i < $opt_loop_count*3 ; $i++) ...@@ -775,7 +777,7 @@ for ($i=0 ; $i < $opt_loop_count*3 ; $i++)
} }
$end_time=new Benchmark; $end_time=new Benchmark;
print "Time for update_with_key ($opt_loop_count): " . print "Time for update_with_key (" . ($opt_loop_count*3) . "): " .
timestr(timediff($end_time, $loop_time),"all") . "\n"; timestr(timediff($end_time, $loop_time),"all") . "\n";
print "\nTesting update of all rows\n"; print "\nTesting update of all rows\n";
...@@ -785,7 +787,7 @@ for ($i=0 ; $i < $small_loop_count ; $i++) ...@@ -785,7 +787,7 @@ for ($i=0 ; $i < $small_loop_count ; $i++)
$sth = $dbh->do("update bench1 set dummy1='updated $i'") or die $DBI::errstr; $sth = $dbh->do("update bench1 set dummy1='updated $i'") or die $DBI::errstr;
} }
$end_time=new Benchmark; $end_time=new Benchmark;
print "Time for update_big ($range_loop_count): " . print "Time for update_big ($small_loop_count): " .
timestr(timediff($end_time, $loop_time),"all") . "\n"; timestr(timediff($end_time, $loop_time),"all") . "\n";
...@@ -859,6 +861,49 @@ if ($server->small_rollback_segment()) ...@@ -859,6 +861,49 @@ if ($server->small_rollback_segment())
$dbh = $server->connect(); $dbh = $server->connect();
} }
####
#### Test INSERT INTO ... SELECT
####
if ($limits->{'insert_select'})
{
print "\nTesting INSERT INTO ... SELECT\n";
do_many($dbh,$server->create("bench2",
["id int NOT NULL",
"id2 int NOT NULL",
"id3 int NOT NULL",
"dummy1 char(30)"],
["primary key (id,id2)"]));
do_many($dbh,$server->create("bench3",
["id int NOT NULL",
"id2 int NOT NULL",
"id3 int NOT NULL",
"dummy1 char(30)"],
["primary key (id,id2)",
"index index_id3 (id3)"]));
$loop_time=new Benchmark;
$sth = $dbh->do("INSERT INTO bench2 SELECT * from bench1") ||
die $DBI::errstr;
$end_time=new Benchmark;
print "Time for insert_select_1_key (1): " .
timestr(timediff($end_time, $loop_time),"all") . "\n";
$loop_time=new Benchmark;
$sth = $dbh->do("INSERT INTO bench3 SELECT * from bench1") ||
die $DBI::errstr;
$end_time=new Benchmark;
print "Time for insert_select_2_keys (1): " .
timestr(timediff($end_time, $loop_time),"all") . "\n";
$loop_time=new Benchmark;
$sth = $dbh->do("DROP TABLE bench2") ||
die $DBI::errstr;
$sth = $dbh->do("DROP TABLE bench3") ||
die $DBI::errstr;
$end_time=new Benchmark;
print "Time for drop table(2): " .
timestr(timediff($end_time, $loop_time),"all") . "\n";
}
#### ####
#### Do some deletes on the table #### Do some deletes on the table
#### ####
......
...@@ -254,7 +254,7 @@ int ha_myisam::check(THD* thd, HA_CHECK_OPT* check_opt) ...@@ -254,7 +254,7 @@ int ha_myisam::check(THD* thd, HA_CHECK_OPT* check_opt)
STATE_CRASHED_ON_REPAIR)) && STATE_CRASHED_ON_REPAIR)) &&
share->state.open_count == 0) || share->state.open_count == 0) ||
((param.testflag & T_FAST) && (share->state.open_count == ((param.testflag & T_FAST) && (share->state.open_count ==
(share->global_changed ? 1 : 0))))) (uint) (share->global_changed ? 1 : 0)))))
return HA_ADMIN_ALREADY_DONE; return HA_ADMIN_ALREADY_DONE;
error = chk_size(&param, file); error = chk_size(&param, file);
...@@ -298,6 +298,7 @@ int ha_myisam::check(THD* thd, HA_CHECK_OPT* check_opt) ...@@ -298,6 +298,7 @@ int ha_myisam::check(THD* thd, HA_CHECK_OPT* check_opt)
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;
} }
check_opt->retry_without_quick=param.retry_without_quick;
return error ? HA_ADMIN_CORRUPT : HA_ADMIN_OK; return error ? HA_ADMIN_CORRUPT : HA_ADMIN_OK;
} }
...@@ -317,7 +318,7 @@ int ha_myisam::analyze(THD *thd, HA_CHECK_OPT* check_opt) ...@@ -317,7 +318,7 @@ int ha_myisam::analyze(THD *thd, HA_CHECK_OPT* check_opt)
myisamchk_init(&param); myisamchk_init(&param);
param.thd = thd; param.thd = thd;
param.op_name = (char*)" analyze"; param.op_name = (char*) "analyze";
param.table_name = table->table_name; param.table_name = table->table_name;
param.testflag=(T_FAST | T_CHECK | T_SILENT | T_STATISTICS | param.testflag=(T_FAST | T_CHECK | T_SILENT | T_STATISTICS |
T_DONT_CHECK_CHECKSUM); T_DONT_CHECK_CHECKSUM);
...@@ -338,6 +339,7 @@ int ha_myisam::analyze(THD *thd, HA_CHECK_OPT* check_opt) ...@@ -338,6 +339,7 @@ int ha_myisam::analyze(THD *thd, HA_CHECK_OPT* check_opt)
return error ? HA_ADMIN_CORRUPT : HA_ADMIN_OK; return error ? HA_ADMIN_CORRUPT : HA_ADMIN_OK;
} }
int ha_myisam::restore(THD* thd, HA_CHECK_OPT *check_opt) int ha_myisam::restore(THD* thd, HA_CHECK_OPT *check_opt)
{ {
HA_CHECK_OPT tmp_check_opt; HA_CHECK_OPT tmp_check_opt;
...@@ -404,6 +406,7 @@ int ha_myisam::backup(THD* thd, HA_CHECK_OPT *check_opt) ...@@ -404,6 +406,7 @@ int ha_myisam::backup(THD* thd, HA_CHECK_OPT *check_opt)
int ha_myisam::repair(THD* thd, HA_CHECK_OPT *check_opt) int ha_myisam::repair(THD* thd, HA_CHECK_OPT *check_opt)
{ {
int error;
if (!file) return HA_ADMIN_INTERNAL_ERROR; if (!file) return HA_ADMIN_INTERNAL_ERROR;
MI_CHECK param; MI_CHECK param;
...@@ -415,7 +418,21 @@ int ha_myisam::repair(THD* thd, HA_CHECK_OPT *check_opt) ...@@ -415,7 +418,21 @@ int ha_myisam::repair(THD* thd, HA_CHECK_OPT *check_opt)
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;
return repair(thd,param,0); while ((error=repair(thd,param,0)))
{
if (param.retry_without_quick && param.opt_rep_quick)
{
param.opt_rep_quick=0;
continue;
}
if ((param.testflag & T_REP_BY_SORT))
{
param.testflag= (param.testflag & ~T_REP_BY_SORT) | T_REP;
continue;
}
break;
}
return error;
} }
int ha_myisam::optimize(THD* thd, HA_CHECK_OPT *check_opt) int ha_myisam::optimize(THD* thd, HA_CHECK_OPT *check_opt)
...@@ -576,19 +593,19 @@ bool ha_myisam::activate_all_index(THD *thd) ...@@ -576,19 +593,19 @@ bool ha_myisam::activate_all_index(THD *thd)
} }
bool ha_myisam::check_and_repair(THD *thd, const char *name) bool ha_myisam::check_and_repair(THD *thd)
{ {
int error=0; int error=0;
HA_CHECK_OPT check_opt; HA_CHECK_OPT check_opt;
DBUG_ENTER("ha_myisam::auto_check_and_repair"); DBUG_ENTER("ha_myisam::auto_check_and_repair");
if (open(name, O_RDWR, HA_OPEN_WAIT_IF_LOCKED))
DBUG_RETURN(1);
check_opt.init(); check_opt.init();
check_opt.flags=T_MEDIUM; check_opt.flags= T_MEDIUM;
check_opt.quick= !file->state->del; // Don't use quick if deleted rows
if (mi_is_crashed(file) || check(thd, &check_opt)) if (mi_is_crashed(file) || check(thd, &check_opt))
{ {
if (check_opt.retry_without_quick)
check_opt.quick=0;
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) ?
...@@ -596,11 +613,14 @@ bool ha_myisam::check_and_repair(THD *thd, const char *name) ...@@ -596,11 +613,14 @@ bool ha_myisam::check_and_repair(THD *thd, const char *name)
if (repair(thd, &check_opt)) if (repair(thd, &check_opt))
error=1; error=1;
} }
if (close())
error=1;
DBUG_RETURN(error); DBUG_RETURN(error);
} }
bool ha_myisam::is_crashed() const
{
return (file->s->state.changed & STATE_CRASHED ||
(my_disable_locking && file->s->state.open_count));
}
int ha_myisam::update_row(const byte * old_data, byte * new_data) int ha_myisam::update_row(const byte * old_data, byte * new_data)
{ {
......
...@@ -45,8 +45,7 @@ class ha_myisam: public handler ...@@ -45,8 +45,7 @@ class ha_myisam: public handler
HA_KEYPOS_TO_RNDPOS | HA_READ_ORDER | HA_LASTKEY_ORDER | HA_KEYPOS_TO_RNDPOS | HA_READ_ORDER | HA_LASTKEY_ORDER |
HA_HAVE_KEY_READ_ONLY | HA_READ_NOT_EXACT_KEY | HA_HAVE_KEY_READ_ONLY | HA_READ_NOT_EXACT_KEY |
HA_LONGLONG_KEYS | HA_NULL_KEY | HA_LONGLONG_KEYS | HA_NULL_KEY |
HA_DUPP_POS | HA_BLOB_KEY | HA_AUTO_PART_KEY | HA_DUPP_POS | HA_BLOB_KEY | HA_AUTO_PART_KEY)
HA_CHECK_AND_REPAIR)
{} {}
~ha_myisam() {} ~ha_myisam() {}
const char *table_type() const { return "MyISAM"; } const char *table_type() const { return "MyISAM"; }
...@@ -103,7 +102,9 @@ class ha_myisam: public handler ...@@ -103,7 +102,9 @@ class ha_myisam: public handler
int check(THD* thd, HA_CHECK_OPT* check_opt); int check(THD* thd, HA_CHECK_OPT* check_opt);
int analyze(THD* thd,HA_CHECK_OPT* check_opt); int analyze(THD* thd,HA_CHECK_OPT* check_opt);
int repair(THD* thd, HA_CHECK_OPT* check_opt); int repair(THD* thd, HA_CHECK_OPT* check_opt);
bool check_and_repair(THD *thd, const char *name); bool check_and_repair(THD *thd);
bool is_crashed() const;
bool auto_repair() const { return myisam_recover_options != 0; }
int optimize(THD* thd, HA_CHECK_OPT* check_opt); int optimize(THD* thd, HA_CHECK_OPT* check_opt);
int restore(THD* thd, HA_CHECK_OPT* check_opt); int restore(THD* thd, HA_CHECK_OPT* check_opt);
int backup(THD* thd, HA_CHECK_OPT* check_opt); int backup(THD* thd, HA_CHECK_OPT* check_opt);
......
...@@ -66,7 +66,6 @@ ...@@ -66,7 +66,6 @@
#define HA_NO_WRITE_DELAYED (HA_NOT_EXACT_COUNT*2) #define HA_NO_WRITE_DELAYED (HA_NOT_EXACT_COUNT*2)
#define HA_PRIMARY_KEY_IN_READ_INDEX (HA_NO_WRITE_DELAYED*2) #define HA_PRIMARY_KEY_IN_READ_INDEX (HA_NO_WRITE_DELAYED*2)
#define HA_DROP_BEFORE_CREATE (HA_PRIMARY_KEY_IN_READ_INDEX*2) #define HA_DROP_BEFORE_CREATE (HA_PRIMARY_KEY_IN_READ_INDEX*2)
#define HA_CHECK_AND_REPAIR (HA_DROP_BEFORE_CREATE*2)
/* Parameters for open() (in register form->filestat) */ /* Parameters for open() (in register form->filestat) */
/* HA_GET_INFO does a implicit HA_ABORT_IF_LOCKED */ /* HA_GET_INFO does a implicit HA_ABORT_IF_LOCKED */
...@@ -146,9 +145,10 @@ typedef struct st_ha_check_opt ...@@ -146,9 +145,10 @@ typedef struct st_ha_check_opt
bool quick; bool quick;
bool changed_files; bool changed_files;
bool optimize; bool optimize;
bool retry_without_quick;
inline void init() inline void init()
{ {
flags= 0; quick= optimize=0; flags= 0; quick= optimize= retry_without_quick=0;
sort_buffer_size = myisam_sort_buffer_size; sort_buffer_size = myisam_sort_buffer_size;
} }
} HA_CHECK_OPT; } HA_CHECK_OPT;
...@@ -249,7 +249,7 @@ public: ...@@ -249,7 +249,7 @@ public:
virtual void update_create_info(HA_CREATE_INFO *create_info) {} virtual void update_create_info(HA_CREATE_INFO *create_info) {}
virtual int check(THD* thd, HA_CHECK_OPT* check_opt ); virtual int check(THD* thd, HA_CHECK_OPT* check_opt );
virtual int repair(THD* thd, HA_CHECK_OPT* check_opt); virtual int repair(THD* thd, HA_CHECK_OPT* check_opt);
virtual bool check_and_repair(THD *thd, const char *name) {return 1;} virtual bool check_and_repair(THD *thd) {return 1;}
virtual int optimize(THD* thd,HA_CHECK_OPT* check_opt); virtual int optimize(THD* thd,HA_CHECK_OPT* check_opt);
virtual int analyze(THD* thd, HA_CHECK_OPT* check_opt); virtual int analyze(THD* thd, HA_CHECK_OPT* check_opt);
virtual int backup(THD* thd, HA_CHECK_OPT* check_opt); virtual int backup(THD* thd, HA_CHECK_OPT* check_opt);
...@@ -274,6 +274,8 @@ public: ...@@ -274,6 +274,8 @@ public:
virtual uint max_key_length()const =0; virtual uint max_key_length()const =0;
virtual uint min_record_length(uint options) const { return 1; } virtual uint min_record_length(uint options) const { return 1; }
virtual bool low_byte_first() const { return 1; } virtual bool low_byte_first() const { return 1; }
virtual bool is_crashed() const { return 0; }
virtual bool auto_repair() const { return 0; }
virtual int rename_table(const char *from, const char *to); virtual int rename_table(const char *from, const char *to);
virtual int delete_table(const char *name); virtual int delete_table(const char *name);
......
...@@ -434,7 +434,10 @@ int lock_table_name(THD *thd, TABLE_LIST *table_list) ...@@ -434,7 +434,10 @@ int lock_table_name(THD *thd, TABLE_LIST *table_list)
table_list->table=table; table_list->table=table;
if (hash_insert(&open_cache, (byte*) table)) if (hash_insert(&open_cache, (byte*) table))
{
my_free((gptr) table,MYF(0));
DBUG_RETURN(-1); DBUG_RETURN(-1);
}
if (remove_table_from_cache(thd, table_list->db, table_list->name)) if (remove_table_from_cache(thd, table_list->db, table_list->name))
DBUG_RETURN(1); // Table is in use DBUG_RETURN(1); // Table is in use
DBUG_RETURN(0); DBUG_RETURN(0);
......
...@@ -261,7 +261,7 @@ void Log_event::print_header(FILE* file) ...@@ -261,7 +261,7 @@ void Log_event::print_header(FILE* file)
{ {
fputc('#', file); fputc('#', file);
print_timestamp(file); print_timestamp(file);
fprintf(file, " server id %d ", server_id); fprintf(file, " server id %ld ", server_id);
} }
void Log_event::print_timestamp(FILE* file, time_t* ts = 0) void Log_event::print_timestamp(FILE* file, time_t* ts = 0)
...@@ -709,7 +709,7 @@ void Load_log_event::print(FILE* file, bool short_form) ...@@ -709,7 +709,7 @@ void Load_log_event::print(FILE* file, bool short_form)
} }
if((int)skip_lines > 0) if((int)skip_lines > 0)
fprintf(file, " IGNORE %d LINES ", skip_lines); fprintf(file, " IGNORE %ld LINES ", skip_lines);
if(num_fields) if(num_fields)
{ {
......
...@@ -34,7 +34,7 @@ HASH open_cache; /* Used by mysql_test */ ...@@ -34,7 +34,7 @@ HASH open_cache; /* Used by mysql_test */
static int open_unireg_entry(TABLE *entry,const char *db,const char *name, static int open_unireg_entry(TABLE *entry,const char *db,const char *name,
const char *alias); const char *alias, bool locked);
static bool insert_fields(THD *thd,TABLE_LIST *tables, const char *table_name, static bool insert_fields(THD *thd,TABLE_LIST *tables, const char *table_name,
List_iterator<Item> *it); List_iterator<Item> *it);
static void free_cache_entry(TABLE *entry); static void free_cache_entry(TABLE *entry);
...@@ -572,7 +572,7 @@ TABLE *reopen_name_locked_table(THD* thd, TABLE_LIST* table_list) ...@@ -572,7 +572,7 @@ TABLE *reopen_name_locked_table(THD* thd, TABLE_LIST* table_list)
key_length=(uint) (strmov(strmov(key,db)+1,table_name)-key)+1; key_length=(uint) (strmov(strmov(key,db)+1,table_name)-key)+1;
pthread_mutex_lock(&LOCK_open); pthread_mutex_lock(&LOCK_open);
if (open_unireg_entry(table, db, table_name, table_name) || if (open_unireg_entry(table, db, table_name, table_name,0) ||
!(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)))
{ {
...@@ -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(table,db,table_name,alias) || if (open_unireg_entry(table,db,table_name,alias,0) ||
!(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)))
{ {
...@@ -816,7 +816,7 @@ bool reopen_table(TABLE *table,bool locked) ...@@ -816,7 +816,7 @@ bool reopen_table(TABLE *table,bool locked)
if (!locked) if (!locked)
VOID(pthread_mutex_lock(&LOCK_open)); VOID(pthread_mutex_lock(&LOCK_open));
if (open_unireg_entry(&tmp,db,table_name,table->table_name)) if (open_unireg_entry(&tmp,db,table_name,table->table_name,locked))
goto end; goto end;
free_io_cache(table); free_io_cache(table);
...@@ -1113,23 +1113,72 @@ void abort_locked_tables(THD *thd,const char *db, const char *table_name) ...@@ -1113,23 +1113,72 @@ void abort_locked_tables(THD *thd,const char *db, const char *table_name)
*/ */
static int open_unireg_entry(TABLE *entry,const char *db,const char *name, static int open_unireg_entry(TABLE *entry,const char *db,const char *name,
const char *alias) const char *alias, bool locked)
{ {
char path[FN_REFLEN]; char path[FN_REFLEN];
int error;
DBUG_ENTER("open_unireg_entry"); DBUG_ENTER("open_unireg_entry");
(void) sprintf(path,"%s/%s/%s",mysql_data_home,db,name); (void) sprintf(path,"%s/%s/%s",mysql_data_home,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),
READ_KEYINFO | COMPUTE_TYPES | EXTRA_RECORD, READ_KEYINFO | COMPUTE_TYPES | EXTRA_RECORD,
ha_open_options, ha_open_options,
entry)) entry))
{ {
DBUG_RETURN(1); THD *thd=current_thd;
if (!entry->crashed)
goto err; // Can't repair the table
TABLE_LIST table_list;
table_list.db=(char*) db;
table_list.name=(char*) name;
table_list.next=0;
if (!locked)
pthread_mutex_lock(&LOCK_open);
if ((error=lock_table_name(thd,&table_list)))
{
if (error < 0)
{
if (!locked)
pthread_mutex_lock(&LOCK_open);
goto err;
}
if (wait_for_locked_table_names(thd,&table_list))
{
unlock_table_name(thd,&table_list);
if (!locked)
pthread_mutex_lock(&LOCK_open);
goto err;
}
}
pthread_mutex_unlock(&LOCK_open);
thd->net.last_error[0]=0; // Clear error message
thd->net.last_errno=0;
error=0;
sql_print_error("Warning: Repairing table: %s.%s",db,name);
if (openfrm(path,alias,
(uint) (HA_OPEN_KEYFILE | HA_OPEN_RNDFILE | HA_GET_INDEX |
HA_TRY_READ_ONLY),
READ_KEYINFO | COMPUTE_TYPES | EXTRA_RECORD,
ha_open_options | HA_OPEN_FOR_REPAIR,
entry) ||
(entry->file->is_crashed() && entry->file->check_and_repair(thd)))
{
sql_print_error("Error: Couldn't repair table: %s.%s",db,name);
error=1;
}
unlock_table_name(thd,&table_list);
if (locked)
pthread_mutex_lock(&LOCK_open); // Get back old lock
if (error)
goto err;
} }
(void) entry->file->extra(HA_EXTRA_NO_READCHECK); // Not needed in SQL (void) entry->file->extra(HA_EXTRA_NO_READCHECK); // Not needed in SQL
DBUG_RETURN(0); DBUG_RETURN(0);
err:
DBUG_RETURN(1);
} }
......
...@@ -127,7 +127,7 @@ class TMP_TABLE_PARAM { ...@@ -127,7 +127,7 @@ class TMP_TABLE_PARAM {
uint group_parts,group_length; uint group_parts,group_length;
uint quick_group; uint quick_group;
TMP_TABLE_PARAM() :group_parts(0),group_length(0),copy_field(0) {} TMP_TABLE_PARAM() :copy_field(0), group_parts(0), group_length(0) {}
~TMP_TABLE_PARAM() ~TMP_TABLE_PARAM()
{ {
cleanup(); cleanup();
......
...@@ -745,61 +745,61 @@ static int prepare_for_restore(THD* thd, TABLE_LIST* table) ...@@ -745,61 +745,61 @@ static int prepare_for_restore(THD* thd, TABLE_LIST* table)
{ {
String *packet = &thd->packet; String *packet = &thd->packet;
if(table->table) // do not overwrite existing tables on restore if (table->table) // do not overwrite existing tables on restore
{ {
return send_check_errmsg(thd, table, "restore", return send_check_errmsg(thd, table, "restore",
"table exists, will not overwrite on restore" "table exists, will not overwrite on restore"
); );
} }
else else
{ {
char* backup_dir = thd->lex.backup_dir; char* backup_dir = thd->lex.backup_dir;
char src_path[FN_REFLEN], dst_path[FN_REFLEN]; char src_path[FN_REFLEN], dst_path[FN_REFLEN];
char* table_name = table->name; char* table_name = table->name;
char* db = thd->db ? thd->db : table->db; char* db = thd->db ? thd->db : table->db;
if(!fn_format(src_path, table_name, backup_dir, reg_ext, 4 + 64)) if (!fn_format(src_path, table_name, backup_dir, reg_ext, 4 + 64))
return -1; // protect buffer overflow return -1; // protect buffer overflow
sprintf(dst_path, "%s/%s/%s", mysql_real_data_home, db, table_name); sprintf(dst_path, "%s/%s/%s", mysql_real_data_home, db, table_name);
int lock_retcode; int lock_retcode;
pthread_mutex_lock(&LOCK_open); pthread_mutex_lock(&LOCK_open);
if((lock_retcode = lock_table_name(thd, table)) < 0) if ((lock_retcode = lock_table_name(thd, table)) < 0)
{ {
pthread_mutex_unlock(&LOCK_open);
return -1;
}
if(lock_retcode && wait_for_locked_table_names(thd, table))
{
pthread_mutex_unlock(&LOCK_open);
return -1;
}
pthread_mutex_unlock(&LOCK_open); pthread_mutex_unlock(&LOCK_open);
return -1;
}
if(my_copy(src_path, if (lock_retcode && wait_for_locked_table_names(thd, table))
fn_format(dst_path, dst_path,"", {
reg_ext, 4), pthread_mutex_unlock(&LOCK_open);
MYF(MY_WME))) return -1;
{ }
return send_check_errmsg(thd, table, "restore", pthread_mutex_unlock(&LOCK_open);
"Failed copying .frm file");
}
bool save_no_send_ok = thd->net.no_send_ok;
thd->net.no_send_ok = 1;
// generate table will try to send OK which messes up the output
// for the client
if(generate_table(thd, table, 0)) if (my_copy(src_path,
{ fn_format(dst_path, dst_path,"",
thd->net.no_send_ok = save_no_send_ok; reg_ext, 4),
return send_check_errmsg(thd, table, "restore", MYF(MY_WME)))
"Failed generating table from .frm file"); {
} return send_check_errmsg(thd, table, "restore",
"Failed copying .frm file");
}
bool save_no_send_ok = thd->net.no_send_ok;
thd->net.no_send_ok = 1;
// generate table will try to send OK which messes up the output
// for the client
if (generate_table(thd, table, 0))
{
thd->net.no_send_ok = save_no_send_ok; thd->net.no_send_ok = save_no_send_ok;
return send_check_errmsg(thd, table, "restore",
"Failed generating table from .frm file");
} }
thd->net.no_send_ok = save_no_send_ok;
}
return 0; return 0;
} }
......
...@@ -1134,8 +1134,13 @@ repair: ...@@ -1134,8 +1134,13 @@ repair:
opt_mi_check_type: opt_mi_check_type:
/* empty */ { Lex->check_opt.flags = T_MEDIUM; } /* empty */ { Lex->check_opt.flags = T_MEDIUM; }
| TYPE_SYM EQ mi_check_types {} | TYPE_SYM EQ mi_check_types {}
| mi_check_types {}
mi_check_types: mi_check_types:
mi_check_type {}
| mi_check_type mi_check_types {}
mi_check_type:
QUICK { Lex->check_opt.quick = 1; } QUICK { Lex->check_opt.quick = 1; }
| FAST_SYM { Lex->check_opt.flags|= T_FAST; } | FAST_SYM { Lex->check_opt.flags|= T_FAST; }
| EXTENDED_SYM { Lex->check_opt.flags|= T_EXTEND; } | EXTENDED_SYM { Lex->check_opt.flags|= T_EXTEND; }
......
...@@ -212,17 +212,24 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag, ...@@ -212,17 +212,24 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
error=2; error=2;
if (db_stat) if (db_stat)
{ {
if ((outparam->file-> int err;
ha_open(index_file, if ((err=(outparam->file->
(db_stat & HA_READ_ONLY ? O_RDONLY : O_RDWR), ha_open(index_file,
(db_stat & HA_OPEN_TEMPORARY ? HA_OPEN_TMP_TABLE : (db_stat & HA_READ_ONLY ? O_RDONLY : O_RDWR),
(db_stat & HA_WAIT_IF_LOCKED || (db_stat & HA_OPEN_TEMPORARY ? HA_OPEN_TMP_TABLE :
specialflag & SPECIAL_WAIT_IF_LOCKED) ? ((db_stat & HA_WAIT_IF_LOCKED) ||
HA_OPEN_WAIT_IF_LOCKED : (specialflag & SPECIAL_WAIT_IF_LOCKED)) ?
(db_stat & (HA_ABORT_IF_LOCKED | HA_GET_INFO)) ? HA_OPEN_WAIT_IF_LOCKED :
HA_OPEN_ABORT_IF_LOCKED : (db_stat & (HA_ABORT_IF_LOCKED | HA_GET_INFO)) ?
HA_OPEN_IGNORE_IF_LOCKED) | ha_open_flags))) HA_OPEN_ABORT_IF_LOCKED :
HA_OPEN_IGNORE_IF_LOCKED) | ha_open_flags))))
{
/* Set a flag if the table is crashed and it can be auto. repaired */
outparam->crashed=(err == HA_ERR_CRASHED &&
outparam->file->auto_repair() &&
!(ha_open_flags & HA_OPEN_FOR_REPAIR));
goto err_not_open; /* purecov: inspected */ goto err_not_open; /* purecov: inspected */
}
} }
outparam->db_low_byte_first=outparam->file->low_byte_first(); outparam->db_low_byte_first=outparam->file->low_byte_first();
...@@ -549,6 +556,7 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag, ...@@ -549,6 +556,7 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
delete crypted; delete crypted;
my_pthread_setspecific_ptr(THR_MALLOC,old_root); my_pthread_setspecific_ptr(THR_MALLOC,old_root);
frm_error(error,outparam,name,ME_ERROR+ME_WAITTANG); frm_error(error,outparam,name,ME_ERROR+ME_WAITTANG);
delete outparam->file;
outparam->file=0; // For easyer errorchecking outparam->file=0; // For easyer errorchecking
free_root(&outparam->mem_root,MYF(0)); free_root(&outparam->mem_root,MYF(0));
my_free(outparam->table_name,MYF(MY_ALLOW_ZERO_PTR)); my_free(outparam->table_name,MYF(MY_ALLOW_ZERO_PTR));
......
...@@ -92,6 +92,7 @@ struct st_table { ...@@ -92,6 +92,7 @@ struct st_table {
my_bool db_low_byte_first; /* Portable row format */ my_bool db_low_byte_first; /* Portable row format */
my_bool locked_by_flush; my_bool locked_by_flush;
my_bool locked_by_name; my_bool locked_by_name;
my_bool crashed;
Field *next_number_field, /* Set if next_number is activated */ Field *next_number_field, /* Set if next_number is activated */
*found_next_number_field, /* Set on open */ *found_next_number_field, /* Set on open */
*rowid_field; *rowid_field;
......
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