Merge paul@work.mysql.com:/home/bk/mysql-4.0

into teton.kitebird.com:/home/paul/mysql-4.0
This commit is contained in:
paul@teton.kitebird.com 2002-02-11 19:23:08 -06:00
commit cc0ec228db
68 changed files with 1051 additions and 971 deletions

View file

@ -19017,7 +19017,7 @@ in MySQL < 4.0.2 whether index is @code{FULLTEXT} or not.
Note that as the @code{Cardinality} is counted based on statistics
stored as integers, it's not necessarily accurate for small tables.
The @code{Null} and @code{Index_type} column was added in MySQL 4.0.2.
The @code{Null} and @code{Index_type} columns were added in MySQL 4.0.2.
@node SHOW TABLE STATUS, SHOW STATUS, SHOW DATABASE INFO, SHOW
@subsubsection @code{SHOW TABLE STATUS}
@ -29836,6 +29836,32 @@ mysql> select 1 IS NOT NULL, 0 IS NOT NULL, NULL IS NOT NULL;
-> 1 1 0
@end example
@cindex ODBC compatibility
@cindex compatibility, with ODBC
To be able to work good with other programs, MySQL supports the following
extra features when using @code{IS NULL}:
@itemize @bullet
@item
You can find the last inserted row with:
@example
SELECT * FROM tbl_name WHERE auto_col IS NULL
@end example
This can be disabled by setting @code{SQL_AUTO_IS_NULL=0}. @xref{SET OPTION}.
@item
For @code{NOT NULL} @code{DATE} and @code{DATETIME} columns you can find
the special date @code{0000-00-00} by using:
@example
SELECT * FROM tbl_name WHERE date_column IS NULL
@end example
This is needed to get some ODBC applications to work (as ODBC doesn't
support a @code{0000-00-00} date)
@end itemize
@findex BETWEEN ... AND
@item expr BETWEEN min AND max
If @code{expr} is greater than or equal to @code{min} and @code{expr} is
@ -32000,7 +32026,7 @@ mysql> select CAST(1 AS UNSIGNED) -2.0
If you are using a string in an arithmetic operation, this is converted
to a floating point number.
The @code{CAST()} and @code{CONVERT()} function was added in MySQL 4.0.2.
The @code{CAST()} and @code{CONVERT()} functions were added in MySQL 4.0.2.
The handing of unsigned values was changed in MySQL 4.0 to be able to
support @code{BIGINT} values properly. If you have some code that you
@ -48385,6 +48411,11 @@ Our TODO section contains what we plan to have in 4.0. @xref{TODO MySQL 4.0}.
@itemize @bullet
@item
Fixed a bug where @code{SQL_CALC_ROWS} returned a wrong value when used
with one table and @code{ORDER BY} and with InnoDB tables.
@item
Fixed that @code{SELECT 0 LIMIT 0} doesn't hang thread.
@item
Fixed some problems with @code{USE KEYS} / @code{IGNORE KEYS} when using
many keys with the same start column.
@item
@ -48393,7 +48424,7 @@ an index that covers the whole row.
@item
Optimized InnoDB sort-buffer handling to take less memory.
@item
Fixed bug in multi-table-delete and InnoDB tables.
Fixed bug in multi table @code{DELETE} and InnoDB tables.
@item
Fixed problem with @code{TRUNCATE} and InnoDB that gave the error
@code{Can't execute the given command because you have active locked
@ -48414,24 +48445,24 @@ repair tables with @code{nan} in float or double columns.
Fixed new bug in @code{myisamchk} where it didn't correctly update number of
``parts'' in the MyISAM index file.
@item
Changed to use autoconf 2.52 (from Autconf 2.13).
Changed to use @code{autoconf} 2.52 (from @code{autoconf} 2.13).
@item
Fixed optimization problem where a MySQL was a long time in a
``preparing'' state when selecting from an empty table which had contained
Fixed optimization problem where the MySQL Server was in ``preparing'' state
for a long time when selecting from an empty table which had contained
a lot of rows.
@item
Fixed bug in complicated join with @code{const} tables. This fix also
improves performance a bit when referring to another table from a
@code{const} table.
@item
First pre-version of multi table updates.
First pre-version of multi table @code{UPDATE}s.
@item
Fixed bug in multi table delete.
Fixed bug in multi table @code{DELETE}.
@item
Fixed bug in @code{SELECT CONCAT(argument-list) ... GROUP BY 1}.
@item
@code{SELECT ... INSERT} did a full rollback in case of an error. Fixed
so that we only roll back the last statement.
@code{INSERT ... SELECT} did a full rollback in case of an error. Fixed
so that we only roll back the last statement in the current transaction.
@item
Fixed bug with empty expression for boolean fulltext search.
@item

View file

@ -192,6 +192,7 @@ Q_ENABLE_QUERY_LOG, Q_DISABLE_QUERY_LOG,
Q_ENABLE_RESULT_LOG, Q_DISABLE_RESULT_LOG,
Q_SERVER_START, Q_SERVER_STOP,Q_REQUIRE_MANAGER,
Q_WAIT_FOR_SLAVE_TO_STOP,
Q_REQUIRE_VERSION,
Q_UNKNOWN, /* Unknown command. */
Q_COMMENT, /* Comments, ignored. */
Q_COMMENT_WITH_COMMAND
@ -228,6 +229,7 @@ const char *command_names[] = {
"enable_result_log", "disable_result_log",
"server_start", "server_stop",
"require_manager", "wait_for_slave_to_stop",
"require_version",
0
};
@ -748,6 +750,42 @@ int do_server_op(struct st_query* q,const char* op)
}
#endif
int do_require_version(struct st_query* q)
{
MYSQL* mysql = &cur_con->mysql;
MYSQL_RES* res;
MYSQL_ROW row;
char* p=q->first_argument, *ver_arg;
uint ver_arg_len,ver_len;
LINT_INIT(res);
if (!*p)
die("Missing version argument in require_version\n");
ver_arg = p;
while (*p && !isspace(*p))
p++;
*p = 0;
ver_arg_len = p - ver_arg;
if (mysql_query(mysql, "select version()") ||
!(res=mysql_store_result(mysql)))
die("Query failed while check server version: %s",
mysql_error(mysql));
if (!(row=mysql_fetch_row(res)) || !row[0])
{
mysql_free_result(res);
die("Strange result from query while checking version");
}
ver_len = strlen(row[0]);
if (ver_len < ver_arg_len || memcmp(row[0],ver_arg,ver_arg_len))
{
mysql_free_result(res);
abort_not_supported_test();
}
mysql_free_result(res);
return 0;
}
int do_source(struct st_query* q)
{
char* p=q->first_argument, *name;
@ -2379,6 +2417,7 @@ int main(int argc, char** argv)
case Q_DISABLE_RESULT_LOG: disable_result_log=1; break;
case Q_SOURCE: do_source(q); break;
case Q_SLEEP: do_sleep(q); break;
case Q_REQUIRE_VERSION: do_require_version(q); break;
case Q_WAIT_FOR_SLAVE_TO_STOP: do_wait_for_slave_to_stop(q); break;
case Q_REQUIRE_MANAGER: do_require_manager(q); break;
#ifndef EMBEDDED_LIBRARY

View file

@ -188,7 +188,7 @@ AC_DEFINE(SPRINTF_RETURNS_INT) AC_MSG_RESULT("int"),
# option, cache_name, variable,
# code to execute if yes, code to exectute if fal
# code to execute if yes, code to exectute if fail
AC_DEFUN(AC_SYS_COMPILER_FLAG,
[
AC_MSG_CHECKING($1)

View file

@ -42,7 +42,6 @@ struct my_option
longlong sub_size; /* Subtract this from given value */
long block_size; /* Value should be a mult. of this */
int app_type; /* To be used by an application */
my_bool opt_is_var; /* If true, the option is a variable */
};
extern int handle_options (int *argc, char ***argv,
@ -50,3 +49,5 @@ extern int handle_options (int *argc, char ***argv,
my_bool (*get_one_option)(int,
const struct my_option *,
char *));
extern void my_print_help(const struct my_option *options);
extern void my_print_variables(const struct my_option *options);

View file

@ -152,71 +152,145 @@ enum options {
static struct my_option my_long_options[] =
{
{"analyze", "", 0, 0, 0, GET_NO_ARG, NO_ARG, 'a', 0, 0, 0, 0, 0, 0, 0},
{"block-search", "", 0, 0, 0, GET_LONG, REQUIRED_ARG, 'b', 0, 0, 0, 0, 0, 0, 0},
{"backup", "", 0, 0, 0, GET_NO_ARG, NO_ARG, 'B', 0, 0, 0, 0, 0, 0, 0},
{"character-sets-dir", "", (gptr*) &set_charset_name, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0, 0, 1},
{"check", "", 0, 0, 0, GET_NO_ARG, NO_ARG, 'c', 0, 0, 0, 0, 0, 0, 0},
{"check-only-changed", "", 0, 0, 0, GET_NO_ARG, NO_ARG, 'C', 0, 0, 0, 0, 0, 0, 0},
{"correct-checksum", "", 0, 0, 0, GET_NO_ARG, NO_ARG, OPT_CORRECT_CHECKSUM, 0, 0, 0, 0, 0, 0, 0},
{"analyze",
"Analyze distribution of keys. Will make some joins in MySQL faster. You can check the calculated distribution.", 0, 0, 0, GET_NO_ARG, NO_ARG, 'a', 0, 0,
0, 0, 0, 0},
{"block-search", "No help available.", 0, 0, 0, GET_LONG, REQUIRED_ARG, 'b',
0, 0, 0, 0, 0, 0},
{"backup", "Make a backup of the .MYD file as 'filename-time.BAK'", 0, 0, 0,
GET_NO_ARG, NO_ARG, 'B', 0, 0, 0, 0, 0, 0},
{"character-sets-dir", "Directory where character sets are.",
(gptr*) &set_charset_name, 0, 0, GET_STR, REQUIRED_ARG, OPT_CHARSETS_DIR, 0,
0, 0, 0, 0, 0},
{"check", "Check table for errors.", 0, 0, 0, GET_NO_ARG, NO_ARG, 'c', 0, 0,
0, 0, 0, 0},
{"check-only-changed",
"Check only tables that has changed since last check.", 0, 0, 0, GET_NO_ARG,
NO_ARG, 'C', 0, 0, 0, 0, 0, 0},
{"correct-checksum", "Correct checksum information for table.", 0, 0, 0,
GET_NO_ARG, NO_ARG, OPT_CORRECT_CHECKSUM, 0, 0, 0, 0, 0, 0},
#ifndef DBUG_OFF
{"debug", "", 0, 0, 0, GET_STR, OPT_ARG, '#', 0, 0, 0, 0, 0, 0, 0},
{"debug", "Output debug log. Often this is 'd:t:o,filename'.", 0, 0, 0,
GET_STR, OPT_ARG, '#', 0, 0, 0, 0, 0, 0},
#endif
{"description", "", 0, 0, 0, GET_NO_ARG, NO_ARG, 'd', 0, 0, 0, 0, 0, 0, 0},
{"data-file-length", "", 0, 0, 0, GET_LONG, REQUIRED_ARG, 'D', 0, 0, 0, 0, 0, 0, 0},
{"extend-check", "", 0, 0, 0, GET_NO_ARG, NO_ARG, 'e', 0, 0, 0, 0, 0, 0, 0},
{"fast", "", 0, 0, 0, GET_NO_ARG, NO_ARG, 'F', 0, 0, 0, 0, 0, 0, 0},
{"force", "", 0, 0, 0, GET_NO_ARG, NO_ARG, 'f', 0, 0, 0, 0, 0, 0, 0},
{"help", "", 0, 0, 0, GET_NO_ARG, NO_ARG, '?', 0, 0, 0, 0, 0, 0, 0},
{"information", "", 0, 0, 0, GET_NO_ARG, NO_ARG, 'i', 0, 0, 0, 0, 0, 0, 0},
{"keys-used", "", 0, 0, 0, GET_LONG, REQUIRED_ARG, 'k', 0, 0, 0, 0, 0, 0, 0},
{"medium-check", "", 0, 0, 0, GET_NO_ARG, NO_ARG, 'm', 0, 0, 0, 0, 0, 0, 0},
{"quick", "", 0, 0, 0, GET_NO_ARG, NO_ARG, 'q', 0, 0, 0, 0, 0, 0, 0},
{"read-only", "", 0, 0, 0, GET_NO_ARG, NO_ARG, 'T', 0, 0, 0, 0, 0, 0, 0},
{"recover", "", 0, 0, 0, GET_NO_ARG, NO_ARG, 'r', 0, 0, 0, 0, 0, 0, 0},
{"safe-recover", "", 0, 0, 0, GET_NO_ARG, NO_ARG, 'o', 0, 0, 0, 0, 0, 0, 0},
{"start-check-pos", "", 0, 0, 0, GET_LONG, REQUIRED_ARG, OPT_START_CHECK_POS, 0, 0, 0, 0, 0, 0, 0},
{"set-auto-increment", "", 0, 0, 0, GET_LONG, OPT_ARG, 'A', 0, 0, 0, 0, 0, 0, 0},
{"set-character-set", "", 0, 0, 0, GET_STR, REQUIRED_ARG, OPT_SET_CHARSET, 0, 0, 0, 0, 0, 0, 0},
{"set-variable", "", 0, 0, 0, GET_STR, REQUIRED_ARG, 'O', 0, 0, 0, 0, 0, 0, 0},
{"silent", "", 0, 0, 0, GET_NO_ARG, NO_ARG, 's', 0, 0, 0, 0, 0, 0, 0},
{"sort-index", "", 0, 0, 0, GET_NO_ARG, NO_ARG, 'S', 0, 0, 0, 0, 0, 0, 0},
{"sort-records", "", 0, 0, 0, GET_LONG, REQUIRED_ARG, 'R', 0, 0, 0, 0, 0, 0, 0},
{"sort-recover", "", 0, 0, 0, GET_NO_ARG, NO_ARG, 'n', 0, 0, 0, 0, 0, 0, 0},
{"tmpdir", "", 0, 0, 0, GET_STR, REQUIRED_ARG, 't', 0, 0, 0, 0, 0, 0, 0},
{"update-state", "", 0, 0, 0, GET_NO_ARG, NO_ARG, 'U', 0, 0, 0, 0, 0, 0, 0},
{"unpack", "", 0, 0, 0, GET_NO_ARG, NO_ARG, 'u', 0, 0, 0, 0, 0, 0, 0},
{"verbose", "", 0, 0, 0, GET_NO_ARG, NO_ARG, 'v', 0, 0, 0, 0, 0, 0, 0},
{"version", "", 0, 0, 0, GET_NO_ARG, NO_ARG, 'V', 0, 0, 0, 0, 0, 0, 0},
{"wait", "", 0, 0, 0, GET_NO_ARG, NO_ARG, 'w', 0, 0, 0, 0, 0, 0, 0},
/* variables begin here */
{ "key_buffer_size", "", (gptr*) &check_param.use_buffers, (gptr*) &check_param.use_buffers, 0, GET_LONG, REQUIRED_ARG, OPT_KEY_BUFFER_SIZE, (long) USE_BUFFER_INIT, (long) MALLOC_OVERHEAD, (long) ~0L, (long) MALLOC_OVERHEAD, (long) IO_SIZE, 0, 1},
{ "myisam_block_size", "", (gptr*) &opt_myisam_block_size, (gptr*) &opt_myisam_block_size, 0, GET_LONG, REQUIRED_ARG, OPT_MYISAM_BLOCK_SIZE, MI_KEY_BLOCK_LENGTH, MI_MIN_KEY_BLOCK_LENGTH, MI_MAX_KEY_BLOCK_LENGTH, 0, MI_MIN_KEY_BLOCK_LENGTH, 0, 1},
{ "read_buffer_size", "", (gptr*) &check_param.read_buffer_length, (gptr*) &check_param.read_buffer_length, 0, GET_LONG, REQUIRED_ARG, OPT_READ_BUFFER_SIZE, (long) READ_BUFFER_INIT, (long) MALLOC_OVERHEAD, (long) ~0L, (long) MALLOC_OVERHEAD, (long) 1L, 0, 1},
{ "write_buffer_size", "", (gptr*) &check_param.write_buffer_length, (gptr*) &check_param.write_buffer_length, 0, GET_LONG, REQUIRED_ARG, OPT_WRITE_BUFFER_SIZE, (long) READ_BUFFER_INIT, (long) MALLOC_OVERHEAD, (long) ~0L, (long) MALLOC_OVERHEAD, (long) 1L, 0, 1},
{ "sort_buffer_size", "", (gptr*) &check_param.sort_buffer_length, (gptr*) &check_param.sort_buffer_length, 0, GET_LONG, REQUIRED_ARG, OPT_SORT_BUFFER_SIZE, (long) SORT_BUFFER_INIT, (long) (MIN_SORT_BUFFER + MALLOC_OVERHEAD), (long) ~0L, (long) MALLOC_OVERHEAD, (long) 1L, 0, 1},
{ "sort_key_blocks", "", (gptr*) &check_param.sort_key_blocks, (gptr*) &check_param.sort_key_blocks, 0, GET_LONG, REQUIRED_ARG, OPT_SORT_KEY_BLOCKS, BUFFERS_WHEN_SORTING, 4L, 100L, 0L, 1L, 0, 1},
{ "decode_bits", "", (gptr*) &decode_bits, (gptr*) &decode_bits, 0, GET_LONG, REQUIRED_ARG, OPT_DECODE_BITS, 9L, 4L, 17L, 0L, 1L, 0, 1},
{ "ft_min_word_len", "", (gptr*) &ft_min_word_len, (gptr*) &ft_min_word_len, 0, GET_LONG, REQUIRED_ARG, OPT_FT_MIN_WORD_LEN, 4, 1, HA_FT_MAXLEN, 0, 1, 0, 1},
{ "ft_max_word_len", "", (gptr*) &ft_max_word_len, (gptr*) &ft_max_word_len, 0, GET_LONG, REQUIRED_ARG, OPT_FT_MAX_WORD_LEN, HA_FT_MAXLEN, 10, HA_FT_MAXLEN, 0, 1, 0, 1},
{ "ft_max_word_len_for_sort", "", (gptr*) &ft_max_word_len_for_sort, (gptr*) &ft_max_word_len_for_sort, 0, GET_LONG, REQUIRED_ARG, OPT_FT_MAX_WORD_LEN_FOR_SORT, 20, 4, HA_FT_MAXLEN, 0, 1, 0, 1},
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
{"description", "Prints some information about table.", 0, 0, 0, GET_NO_ARG,
NO_ARG, 'd', 0, 0, 0, 0, 0, 0},
{"data-file-length",
"Max length of data file (when recreating data-file when it's full).",
(gptr*) &check_param.max_data_file_length,
(gptr*) &check_param.max_data_file_length, 0, GET_LONG, REQUIRED_ARG, 'D',
0, 0, 0, 0, 0, 0},
{"extend-check",
"Try to recover every possible row from the data file. Normally this will also find a lot of garbage rows; Don't use this option if you are not totally desperate.", 0, 0, 0, GET_NO_ARG, NO_ARG, 'e', 0, 0, 0, 0, 0, 0},
{"fast", "Check only tables that hasn't been closed properly.", 0, 0, 0,
GET_NO_ARG, NO_ARG, 'F', 0, 0, 0, 0, 0, 0},
{"force",
"Restart with -r if there are any errors in the table. States will be updated as with --update-state.", 0, 0, 0, GET_NO_ARG, NO_ARG, 'f', 0, 0, 0, 0, 0,
0},
{"help", "Display this help and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG, '?', 0,
0, 0, 0, 0, 0},
{"information", "Print statistics information about table that is checked.",
0, 0, 0, GET_NO_ARG, NO_ARG, 'i', 0, 0, 0, 0, 0, 0},
{"keys-used", "Tell MyISAM to update only some specific keys. # is a bit mask of which keys to use. This can be used to get faster inserts!",
(gptr*) &check_param.keys_in_use, (gptr*) &check_param.keys_in_use, 0,
GET_LL, REQUIRED_ARG, 'k', -1LL, 0, 0, 0, 0, 0},
{"medium-check",
"Faster than extended-check, but only finds 99.99% of all errors. Should be good enough for most cases.", 0, 0, 0, GET_NO_ARG, NO_ARG, 'm', 0, 0, 0, 0, 0,
0},
{"quick", "Faster repair by not modifying the data file.", 0, 0, 0,
GET_NO_ARG, NO_ARG, 'q', 0, 0, 0, 0, 0, 0},
{"read-only", "Don't mark table as checked.", 0, 0, 0, GET_NO_ARG, NO_ARG,
'T', 0, 0, 0, 0, 0, 0},
{"recover",
"Can fix almost anything except unique keys that aren't unique.", 0, 0, 0,
GET_NO_ARG, NO_ARG, 'r', 0, 0, 0, 0, 0, 0},
{"safe-recover",
"Uses old recovery method; Slower than '-r' but can handle a couple of cases where '-r' reports that it can't fix the data file.", 0, 0, 0, GET_NO_ARG,
NO_ARG, 'o', 0, 0, 0, 0, 0, 0},
{"start-check-pos", "No help available.", 0, 0, 0, GET_LONG, REQUIRED_ARG,
OPT_START_CHECK_POS, 0, 0, 0, 0, 0, 0},
{"set-auto-increment",
"Force auto_increment to start at this or higher value. If no value is given, then sets the next auto_increment value to the highest used value for the auto key + 1.", (gptr*) &check_param.auto_increment_value,
(gptr*) &check_param.auto_increment_value, 0, GET_LONG, OPT_ARG, 'A', 0, 0,
0, 0, 0, 0},
{"set-character-set", "Change the character set used by the index", 0, 0, 0,
GET_STR, REQUIRED_ARG, OPT_SET_CHARSET, 0, 0, 0, 0, 0, 0},
{"set-variable", "Change the value of a variable. Please note that this option is depricated; you can set variables directly with --variable-name=value.",
0, 0, 0, GET_STR, REQUIRED_ARG, 'O', 0, 0, 0, 0, 0, 0},
{"silent",
"Only print errors. One can use two -s to make myisamchk very silent.", 0,
0, 0, GET_NO_ARG, NO_ARG, 's', 0, 0, 0, 0, 0, 0},
{"sort-index",
"Sort index blocks. This speeds up 'read-next' in applications.", 0, 0, 0,
GET_NO_ARG, NO_ARG, 'S', 0, 0, 0, 0, 0, 0},
{"sort-records",
"Sort records according to an index. This makes your data much more localized and may speed up things. (It may be VERY slow to do a sort the first time!)",
(gptr*) &check_param.opt_sort_key, (gptr*) &check_param.opt_sort_key, 0,
GET_LONG, REQUIRED_ARG, 'R', 0, 0, 0, 0, 0, 0},
{"sort-recover",
"Force recovering with sorting even if the temporary file was very big.",
0, 0, 0, GET_NO_ARG, NO_ARG, 'n', 0, 0, 0, 0, 0, 0},
{"tmpdir", "Path for temporary files.", (gptr*) &check_param.tmpdir, 0, 0,
GET_STR, REQUIRED_ARG, 't', 0, 0, 0, 0, 0, 0},
{"update-state", "Mark tables as crashed if any errors were found.", 0, 0,
0, GET_NO_ARG, NO_ARG, 'U', 0, 0, 0, 0, 0, 0},
{"unpack", "Unpack file packed with myisampack.", 0, 0, 0, GET_NO_ARG,
NO_ARG, 'u', 0, 0, 0, 0, 0, 0},
{"verbose",
"Print more information. This can be used with --describe and --check. Use many -v for more verbosity!", 0, 0, 0, GET_NO_ARG, NO_ARG, 'v', 0, 0, 0, 0, 0,
0},
{"version", "Print version and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG, 'V', 0,
0, 0, 0, 0, 0},
{"wait", "Wait if table is locked.", 0, 0, 0, GET_NO_ARG, NO_ARG, 'w', 0, 0,
0, 0, 0, 0},
{ "key_buffer_size", "", (gptr*) &check_param.use_buffers,
(gptr*) &check_param.use_buffers, 0, GET_LONG, REQUIRED_ARG,
OPT_KEY_BUFFER_SIZE, (long) USE_BUFFER_INIT, (long) MALLOC_OVERHEAD,
(long) ~0L, (long) MALLOC_OVERHEAD, (long) IO_SIZE, 0},
{ "myisam_block_size", "", (gptr*) &opt_myisam_block_size,
(gptr*) &opt_myisam_block_size, 0, GET_LONG, REQUIRED_ARG,
OPT_MYISAM_BLOCK_SIZE, MI_KEY_BLOCK_LENGTH, MI_MIN_KEY_BLOCK_LENGTH,
MI_MAX_KEY_BLOCK_LENGTH, 0, MI_MIN_KEY_BLOCK_LENGTH, 0},
{ "read_buffer_size", "", (gptr*) &check_param.read_buffer_length,
(gptr*) &check_param.read_buffer_length, 0, GET_LONG, REQUIRED_ARG,
OPT_READ_BUFFER_SIZE, (long) READ_BUFFER_INIT, (long) MALLOC_OVERHEAD,
(long) ~0L, (long) MALLOC_OVERHEAD, (long) 1L, 0},
{ "write_buffer_size", "", (gptr*) &check_param.write_buffer_length,
(gptr*) &check_param.write_buffer_length, 0, GET_LONG, REQUIRED_ARG,
OPT_WRITE_BUFFER_SIZE, (long) READ_BUFFER_INIT, (long) MALLOC_OVERHEAD,
(long) ~0L, (long) MALLOC_OVERHEAD, (long) 1L, 0},
{ "sort_buffer_size", "", (gptr*) &check_param.sort_buffer_length,
(gptr*) &check_param.sort_buffer_length, 0, GET_LONG, REQUIRED_ARG,
OPT_SORT_BUFFER_SIZE, (long) SORT_BUFFER_INIT,
(long) (MIN_SORT_BUFFER + MALLOC_OVERHEAD), (long) ~0L,
(long) MALLOC_OVERHEAD, (long) 1L, 0},
{ "sort_key_blocks", "", (gptr*) &check_param.sort_key_blocks,
(gptr*) &check_param.sort_key_blocks, 0, GET_LONG, REQUIRED_ARG,
OPT_SORT_KEY_BLOCKS, BUFFERS_WHEN_SORTING, 4L, 100L, 0L, 1L, 0},
{ "decode_bits", "", (gptr*) &decode_bits, (gptr*) &decode_bits, 0,
GET_LONG, REQUIRED_ARG, OPT_DECODE_BITS, 9L, 4L, 17L, 0L, 1L, 0},
{ "ft_min_word_len", "", (gptr*) &ft_min_word_len, (gptr*) &ft_min_word_len,
0, GET_LONG, REQUIRED_ARG, OPT_FT_MIN_WORD_LEN, 4, 1, HA_FT_MAXLEN, 0, 1,
0},
{ "ft_max_word_len", "", (gptr*) &ft_max_word_len, (gptr*) &ft_max_word_len,
0, GET_LONG, REQUIRED_ARG, OPT_FT_MAX_WORD_LEN, HA_FT_MAXLEN, 10,
HA_FT_MAXLEN, 0, 1, 0},
{ "ft_max_word_len_for_sort", "", (gptr*) &ft_max_word_len_for_sort,
(gptr*) &ft_max_word_len_for_sort, 0, GET_LONG, REQUIRED_ARG,
OPT_FT_MAX_WORD_LEN_FOR_SORT, 20, 4, HA_FT_MAXLEN, 0, 1, 0},
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
};
static void print_version(void)
{
printf("%s Ver 2.2 for %s at %s\n", my_progname, SYSTEM_TYPE,
printf("%s Ver 2.3 for %s at %s\n", my_progname, SYSTEM_TYPE,
MACHINE_TYPE);
}
static void usage(void)
{
uint i;
print_version();
puts("By Monty, for your professional use");
puts("This software comes with NO WARRANTY: see the PUBLIC for details.\n");
@ -297,17 +371,9 @@ static void usage(void)
data much more localized and may speed up things\n\
(It may be VERY slow to do a sort the first time!)");
print_defaults("my",load_default_groups);
printf("\nThe variables you can set are:\n");
for (i=0; my_long_options[i].name ; i++)
{
if (!my_long_options[i].opt_is_var)
continue;
#ifdef TO_BE_FIXED
printf("%-20s current value: %lu\n", my_long_options[i].name,
*my_long_options[i].value);
#endif
}
print_defaults("my", load_default_groups);
putchar('\n');
my_print_variables(my_long_options);
}
@ -318,127 +384,217 @@ get_one_option(int optid,
const struct my_option *opt __attribute__((unused)),
char *argument)
{
uint old_testflag;
switch (optid) {
case 'a':
check_param.testflag|= T_STATISTICS;
if (argument && *argument == '0')
check_param.testflag&= ~T_STATISTICS;
else
check_param.testflag|= T_STATISTICS;
break;
case 'A':
if (argument)
check_param.auto_increment_value=strtoull(argument, NULL, 0);
check_param.auto_increment_value= strtoull(argument, NULL, 0);
else
check_param.auto_increment_value=0; /* Set to max used value */
check_param.auto_increment_value= 0; /* Set to max used value */
check_param.testflag|= T_AUTO_INC;
break;
case 'b':
check_param.search_after_block=strtoul(argument, NULL, 10);
check_param.search_after_block= strtoul(argument, NULL, 10);
break;
case 'B':
check_param.testflag|= T_BACKUP_DATA;
if (argument && *argument == '0')
check_param.testflag&= ~T_BACKUP_DATA;
else
check_param.testflag|= T_BACKUP_DATA;
break;
case 'c':
check_param.testflag|= T_CHECK;
if (argument && *argument == '0')
check_param.testflag&= ~T_CHECK;
else
check_param.testflag|= T_CHECK;
break;
case 'C':
check_param.testflag|= T_CHECK | T_CHECK_ONLY_CHANGED;
if (argument && *argument == '0')
check_param.testflag&= ~(T_CHECK | T_CHECK_ONLY_CHANGED);
else
check_param.testflag|= T_CHECK | T_CHECK_ONLY_CHANGED;
break;
case 'D':
check_param.max_data_file_length=strtoll(argument, NULL, 10);
break;
case 's': /* silent */
if (check_param.testflag & T_SILENT)
check_param.testflag|=T_VERY_SILENT;
check_param.testflag|= T_SILENT;
check_param.testflag&= ~T_WRITE_LOOP;
if (argument && *argument == '0')
check_param.testflag&= ~(T_SILENT | T_VERY_SILENT);
else
{
if (check_param.testflag & T_SILENT)
check_param.testflag|= T_VERY_SILENT;
check_param.testflag|= T_SILENT;
check_param.testflag&= ~T_WRITE_LOOP;
}
break;
case 'w':
check_param.testflag|= T_WAIT_FOREVER;
if (argument && *argument == '0')
check_param.testflag&= ~T_WAIT_FOREVER;
else
check_param.testflag|= T_WAIT_FOREVER;
break;
case 'd': /* description if isam-file */
check_param.testflag|= T_DESCRIPT;
if (argument && *argument == '0')
check_param.testflag&= ~T_DESCRIPT;
else
check_param.testflag|= T_DESCRIPT;
break;
case 'e': /* extend check */
check_param.testflag|= T_EXTEND;
if (argument && *argument == '0')
check_param.testflag&= ~T_EXTEND;
else
check_param.testflag|= T_EXTEND;
break;
case 'i':
check_param.testflag|= T_INFO;
if (argument && *argument == '0')
check_param.testflag&= ~T_INFO;
else
check_param.testflag|= T_INFO;
break;
case 'f':
check_param.tmpfile_createflag= O_RDWR | O_TRUNC;
check_param.testflag|= T_FORCE_CREATE | T_UPDATE_STATE;
if (argument && *argument == '0')
{
check_param.tmpfile_createflag= O_RDWR | O_TRUNC | O_EXCL;
check_param.testflag&= ~(T_FORCE_CREATE | T_UPDATE_STATE);
}
else
{
check_param.tmpfile_createflag= O_RDWR | O_TRUNC;
check_param.testflag|= T_FORCE_CREATE | T_UPDATE_STATE;
}
break;
case 'F':
check_param.testflag|=T_FAST;
if (argument && *argument == '0')
check_param.testflag&= ~T_FAST;
else
check_param.testflag|= T_FAST;
break;
case 'k':
check_param.keys_in_use= (ulonglong) strtoll(argument, NULL, 10);
break;
case 'm':
check_param.testflag|= T_MEDIUM; /* Medium check */
if (argument && *argument == '0')
check_param.testflag&= ~T_MEDIUM;
else
check_param.testflag|= T_MEDIUM; /* Medium check */
break;
case 'r': /* Repair table */
check_param.testflag= (check_param.testflag & ~T_REP) | T_REP_BY_SORT;
if (argument && *argument == '0')
check_param.testflag&= ~(T_REP | T_REP_BY_SORT);
else
check_param.testflag= (check_param.testflag & ~T_REP) | T_REP_BY_SORT;
break;
case 'o':
check_param.testflag= (check_param.testflag & ~T_REP_BY_SORT) | T_REP;
check_param.force_sort=0;
my_disable_async_io=1; /* More safety */
if (argument && *argument == '0')
{
check_param.testflag&= ~(T_REP | T_REP_BY_SORT);
check_param.force_sort= 0;
}
else
{
check_param.testflag= (check_param.testflag & ~T_REP_BY_SORT) | T_REP;
check_param.force_sort= 0;
my_disable_async_io= 1; /* More safety */
}
break;
case 'n':
check_param.testflag= (check_param.testflag & ~T_REP) | T_REP_BY_SORT;
check_param.force_sort=1;
if (argument && *argument == '0')
{
check_param.testflag&= ~(T_REP | T_REP_BY_SORT);
check_param.force_sort= 0;
}
else
{
check_param.testflag= (check_param.testflag & ~T_REP) | T_REP_BY_SORT;
check_param.force_sort= 1;
}
break;
case 'q':
check_param.opt_rep_quick++;
if (argument && *argument == '0')
check_param.opt_rep_quick=0;
else
check_param.opt_rep_quick++;
break;
case 'u':
check_param.testflag|= T_UNPACK | T_REP_BY_SORT;
if (argument && *argument == '0')
check_param.testflag&= ~(T_UNPACK | T_REP_BY_SORT);
else
check_param.testflag|= T_UNPACK | T_REP_BY_SORT;
break;
case 'v': /* Verbose */
check_param.testflag|= T_VERBOSE;
check_param.verbose++;
if (argument && *argument == '0')
{
check_param.testflag&= ~T_VERBOSE;
check_param.verbose=0;
}
else
{
check_param.testflag|= T_VERBOSE;
check_param.verbose++;
}
break;
case 'R': /* Sort records */
old_testflag=check_param.testflag;
check_param.testflag|= T_SORT_RECORDS;
check_param.opt_sort_key=(uint) atoi(argument) - 1;
if (check_param.opt_sort_key >= MI_MAX_KEY)
if (argument && *argument == '0')
check_param.testflag&= ~T_SORT_RECORDS;
else
{
fprintf(stderr,
"The value of the sort key is bigger than max key: %d.\n",
MI_MAX_KEY);
exit(1);
check_param.testflag|= T_SORT_RECORDS;
check_param.opt_sort_key= (uint) atoi(argument) - 1;
if (check_param.opt_sort_key >= MI_MAX_KEY)
{
fprintf(stderr,
"The value of the sort key is bigger than max key: %d.\n",
MI_MAX_KEY);
exit(1);
}
}
break;
case 'S': /* Sort index */
old_testflag=check_param.testflag;
check_param.testflag|= T_SORT_INDEX;
break;
case 't':
check_param.tmpdir=argument;
if (argument && *argument == '0')
check_param.testflag&= ~T_SORT_INDEX;
else
check_param.testflag|= T_SORT_INDEX;
break;
case 'T':
check_param.testflag|= T_READONLY;
if (argument && *argument == '0')
check_param.testflag&= ~T_READONLY;
else
check_param.testflag|= T_READONLY;
break;
case 'U':
check_param.testflag|= T_UPDATE_STATE;
if (argument && *argument == '0')
check_param.testflag&= ~T_UPDATE_STATE;
else
check_param.testflag|= T_UPDATE_STATE;
break;
case '#':
DBUG_PUSH(argument ? argument : "d:t:o,/tmp/myisamchk.trace");
if (argument && *argument == '0')
{
DBUG_POP();
}
else
{
DBUG_PUSH(argument ? argument : "d:t:o,/tmp/myisamchk.trace");
}
break;
case 'V':
print_version();
exit(0);
case OPT_CORRECT_CHECKSUM:
if (*argument && *argument == '0')
if (argument && *argument == '0')
check_param.testflag&= ~T_CALC_CHECKSUM;
else
check_param.testflag|=T_CALC_CHECKSUM;
check_param.testflag|= T_CALC_CHECKSUM;
break;
#ifdef DEBUG /* Only useful if debugging */
case OPT_START_CHECK_POS:
check_param.start_check_pos=strtoull(argument, NULL, 0);
check_param.start_check_pos= strtoull(argument, NULL, 0);
break;
#endif
case '?':

View file

@ -20,6 +20,7 @@ TZ=GMT-3; export TZ # for UNIX_TIMESTAMP tests to work
#--
PATH=/bin:/usr/bin:/usr/local/bin:/usr/bsd:/usr/X11R6/bin:/usr/openwin/bin
MASTER_40_ARGS="--rpl-recovery-rank=1 --init-rpl-role=master"
# Standard functions
@ -58,7 +59,7 @@ sleep_until_file_deleted ()
done
}
sleep_until_file_exists ()
sleep_until_file_created ()
{
file=$1
loop=$2
@ -190,6 +191,11 @@ while test $# -gt 0; do
--user=*) DBUSER=`$ECHO "$1" | $SED -e "s;--user=;;"` ;;
--force) FORCE=1 ;;
--verbose-manager) MANAGER_QUIET_OPT="" ;;
--old-master) MASTER_40_ARGS="";;
--master-binary=*)
MASTER_MYSQLD=`$ECHO "$1" | $SED -e "s;--master-binary=;;"` ;;
--slave-binary=*)
SLAVE_MYSQLD=`$ECHO "$1" | $SED -e "s;--slave-binary=;;"` ;;
--local) USE_RUNNING_SERVER="" ;;
--tmpdir=*) MYSQL_TMP_DIR=`$ECHO "$1" | $SED -e "s;--tmpdir=;;"` ;;
--local-master)
@ -394,6 +400,16 @@ else
fi
fi
if [ -z "$MASTER_MYSQLD" ]
then
MASTER_MYSQLD=$MYSQLD
fi
if [ -z "$SLAVE_MYSQLD" ]
then
SLAVE_MYSQLD=$MYSQLD
fi
# If we should run all tests cases, we will use a local server for that
if [ -z "$1" ]
@ -430,7 +446,6 @@ GPROF_DIR=$MYSQL_TMP_DIR/gprof
GPROF_MASTER=$GPROF_DIR/master.gprof
GPROF_SLAVE=$GPROF_DIR/slave.gprof
TIMEFILE="$MYSQL_TEST_DIR/var/log/mysqltest-time"
SLAVE_MYSQLD=$MYSQLD #this can be changed later if we are doing gcov
XTERM=`which xterm`
#++
@ -564,11 +579,11 @@ gprof_prepare ()
gprof_collect ()
{
if [ -f $MASTER_MYDDIR/gmon.out ]; then
gprof $MYSQLD $MASTER_MYDDIR/gmon.out > $GPROF_MASTER
gprof $MASTER_MYSQLD $MASTER_MYDDIR/gmon.out > $GPROF_MASTER
echo "Master execution profile has been saved in $GPROF_MASTER"
fi
if [ -f $SLAVE_MYDDIR/gmon.out ]; then
gprof $MYSQLD $SLAVE_MYDDIR/gmon.out > $GPROF_SLAVE
gprof $SLAVE_MYSQLD $SLAVE_MYDDIR/gmon.out > $GPROF_SLAVE
echo "Slave execution profile has been saved in $GPROF_SLAVE"
fi
}
@ -708,8 +723,8 @@ start_master()
if [ -z "$DO_BENCH" ]
then
master_args="--no-defaults --log-bin=$MYSQL_TEST_DIR/var/log/master-bin \
--server-id=1 --rpl-recovery-rank=1 \
--basedir=$MY_BASEDIR --init-rpl-role=master \
--server-id=1 \
--basedir=$MY_BASEDIR \
--port=$MASTER_MYPORT \
--exit-info=256 \
--core \
@ -722,6 +737,7 @@ start_master()
--tmpdir=$MYSQL_TMP_DIR \
--language=$LANGUAGE \
--innodb_data_file_path=ibdata1:50M \
$MASTER_40_ARGS \
$SMALL_SERVER \
$EXTRA_MASTER_OPT $EXTRA_MASTER_MYSQLD_OPT"
else
@ -738,6 +754,7 @@ start_master()
--tmpdir=$MYSQL_TMP_DIR \
--language=$LANGUAGE \
--innodb_data_file_path=ibdata1:50M \
$MASTER_40_ARGS \
$SMALL_SERVER \
$EXTRA_MASTER_OPT $EXTRA_MASTER_MYSQLD_OPT"
fi
@ -749,14 +766,14 @@ start_master()
then
$ECHO "set args $master_args" > $GDB_MASTER_INIT
manager_launch master ddd -display $DISPLAY --debugger \
"gdb -x $GDB_MASTER_INIT" $MYSQLD
"gdb -x $GDB_MASTER_INIT" $MASTER_MYSQLD
elif [ x$DO_GDB = x1 ]
then
if [ x$MANUAL_GDB = x1 ]
then
$ECHO "set args $master_args" > $GDB_MASTER_INIT
$ECHO "To start gdb for the master , type in another window:"
$ECHO "cd $CWD ; gdb -x $GDB_MASTER_INIT $MYSQLD"
$ECHO "cd $CWD ; gdb -x $GDB_MASTER_INIT $MASTER_MYSQLD"
wait_for_master=1500
else
( $ECHO set args $master_args;
@ -770,12 +787,12 @@ r
EOF
fi ) > $GDB_MASTER_INIT
manager_launch master $XTERM -display $DISPLAY \
-title "Master" -e gdb -x $GDB_MASTER_INIT $MYSQLD
-title "Master" -e gdb -x $GDB_MASTER_INIT $MASTER_MYSQLD
fi
else
manager_launch master $MYSQLD $master_args
manager_launch master $MASTER_MYSQLD $master_args
fi
sleep_until_file_exists $MASTER_MYPID $wait_for_master
sleep_until_file_created $MASTER_MYPID $wait_for_master
wait_for_master=$SLEEP_TIME_FOR_SECOND_MASTER
MASTER_RUNNING=1
}
@ -866,7 +883,7 @@ start_slave()
if [ x$MANUAL_GDB = x1 ]
then
echo "To start gdb for the slave, type in another window:"
echo "cd $CWD ; gdb -x $GDB_SLAVE_INIT $MYSQLD"
echo "cd $CWD ; gdb -x $GDB_SLAVE_INIT $SLAVE_MYSQLD"
wait_for_slave=1500
else
manager_launch $slave_ident $XTERM -display $DISPLAY -title "Slave" -e \
@ -876,7 +893,7 @@ start_slave()
manager_launch $slave_ident $SLAVE_MYSQLD $slave_args
fi
eval "SLAVE$1_RUNNING=1"
sleep_until_file_exists $slave_pid $wait_for_slave
sleep_until_file_created $slave_pid $wait_for_slave
wait_for_slave=$SLEEP_TIME_FOR_SECOND_SLAVE
}

View file

@ -48,3 +48,5 @@ i
2
1
drop table t1;
select 0 limit 0;
0

View file

@ -7,7 +7,7 @@ use test;
drop table if exists t1,t3;
create table t1 (word char(20) not null);
load data infile '../../std_data/words.dat' into table t1;
load data local infile '/home/sasha/bk/mysql-4.0/mysql-test/std_data/words.dat' into table t1;
load data local infile 'MYSQL_TEST_DIR/std_data/words.dat' into table t1;
select * from t1;
word
Aarhus

View file

@ -0,0 +1,77 @@
slave stop;
reset master;
reset slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
slave start;
use test;
drop table if exists t1,t3;
create table t1 (word char(20) not null);
load data infile '../../std_data/words.dat' into table t1;
select * from t1;
word
Aarhus
Aaron
Ababa
aback
abaft
abandon
abandoned
abandoning
abandonment
abandons
set password for root@"localhost" = password('foo');
set password for root@"localhost" = password('');
create table t3(n int);
insert into t3 values(1),(2);
use test;
select * from t3;
n
1
2
select sum(length(word)) from t1;
sum(length(word))
71
drop table t1,t3;
reset master;
slave stop;
reset slave;
create table t1(n int);
insert into t1 values (1),(2),(3);
create table t2(id int);
insert into t2 values(connection_id());
create temporary table t1_temp(n int);
insert into t1_temp select get_lock('crash_lock%20C', 1) from t2;
update t1 set n = n + get_lock('crash_lock%20C', 2);
select (@id := id) - id from t2;
(@id := id) - id
0
kill @id;
drop table t2;
Server shutdown in progress
slave start;
set sql_slave_skip_counter=1;
slave start;
select count(*) from t1;
count(*)
3
drop table t1;
create table t1 (n int);
insert into t1 values(3456);
use mysql;
insert into user (Host, User, Password)
VALUES ("10.10.10.%", "blafasel2", password("blafasel2"));
select select_priv,user from mysql.user where user = 'blafasel2';
select_priv user
N blafasel2
update user set Select_priv = "Y" where User="blafasel2";
select select_priv,user from mysql.user where user = 'blafasel2';
select_priv user
Y blafasel2
use test;
select n from t1;
n
3456
select select_priv,user from mysql.user where user = 'blafasel2';
select_priv user
Y blafasel2
drop table t1;

View file

@ -1331,10 +1331,10 @@ table type possible_keys key key_len ref rows Extra
t2 ref fld3 fld3 30 const 1 where used; Using index
explain select fld3 from t2 ignore index (fld3) where fld3 = 'honeysuckle';
table type possible_keys key key_len ref rows Extra
t2 index fld3 fld3 30 NULL 1199 where used; Using index
t2 index NULL fld3 30 NULL 1199 where used; Using index
explain select fld3 from t2 use index (fld1) where fld3 = 'honeysuckle';
table type possible_keys key key_len ref rows Extra
t2 index fld3 fld3 30 NULL 1199 where used; Using index
t2 index NULL fld3 30 NULL 1199 where used; Using index
explain select fld3 from t2 use index (fld3) where fld3 = 'honeysuckle';
table type possible_keys key key_len ref rows Extra
t2 ref fld3 fld3 30 const 1 where used; Using index

View file

@ -45,3 +45,20 @@ select found_rows();
FOUND_ROWS()
8
drop table t1;
create table t1 (a int not null primary key);
insert into t1 values (1),(2),(3),(4),(5);
select sql_calc_found_rows a from t1 where a in (1,2,3) order by a desc limit 0,2;
a
3
2
select FOUND_ROWS();
FOUND_ROWS()
3
select sql_calc_found_rows a from t1 where a in (1,2,3) order by a+2 desc limit 0,2;
a
3
2
select FOUND_ROWS();
FOUND_ROWS()
3
drop table t1;

View file

@ -28,3 +28,5 @@ delete from t1 limit 0;
update t1 set i=3 limit 0;
select * from t1;
drop table t1;
select 0 limit 0;

View file

@ -5,6 +5,7 @@ use test;
drop table if exists t1,t3;
create table t1 (word char(20) not null);
load data infile '../../std_data/words.dat' into table t1;
--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR
eval load data local infile '$MYSQL_TEST_DIR/std_data/words.dat' into table t1;
select * from t1;
set password for root@"localhost" = password('foo');

View file

@ -0,0 +1,86 @@
eval_result;
source include/master-slave.inc;
connection master;
require_version 3.23;
use test;
drop table if exists t1,t3;
create table t1 (word char(20) not null);
load data infile '../../std_data/words.dat' into table t1;
select * from t1;
set password for root@"localhost" = password('foo');
set password for root@"localhost" = password('');
create table t3(n int);
insert into t3 values(1),(2);
save_master_pos;
connection slave;
sync_with_master;
use test;
select * from t3;
select sum(length(word)) from t1;
connection master;
drop table t1,t3;
save_master_pos;
connection slave;
sync_with_master;
#test handling of aborted connection in the middle of update
connection master;
reset master;
connection slave;
slave stop;
reset slave;
connection master;
create table t1(n int);
insert into t1 values (1),(2),(3);
create table t2(id int);
insert into t2 values(connection_id());
save_master_pos;
connection master1;
#avoid generating result
create temporary table t1_temp(n int);
insert into t1_temp select get_lock('crash_lock%20C', 1) from t2;
connection master;
send update t1 set n = n + get_lock('crash_lock%20C', 2);
connection master1;
sleep 2;
select (@id := id) - id from t2;
kill @id;
drop table t2;
connection master;
--error 1053;
reap;
connection slave;
slave start;
sync_with_master ;
#now slave will hit an error
wait_for_slave_to_stop;
set sql_slave_skip_counter=1;
slave start;
select count(*) from t1;
connection master1;
drop table t1;
create table t1 (n int);
insert into t1 values(3456);
use mysql;
insert into user (Host, User, Password)
VALUES ("10.10.10.%", "blafasel2", password("blafasel2"));
select select_priv,user from mysql.user where user = 'blafasel2';
update user set Select_priv = "Y" where User="blafasel2";
select select_priv,user from mysql.user where user = 'blafasel2';
use test;
save_master_pos;
connection slave;
sync_with_master;
select n from t1;
select select_priv,user from mysql.user where user = 'blafasel2';
connection master1;
drop table t1;
save_master_pos;
connection slave;
sync_with_master;

View file

@ -18,3 +18,15 @@ select found_rows();
select SQL_CALC_FOUND_ROWS * from t1 left join t1 as t2 on (t1.b=t2.a) limit 2,1;
select found_rows();
drop table t1;
#
# Test SQL_CALC_FOUND_ROWS optimization when used with one table and filesort
#
create table t1 (a int not null primary key);
insert into t1 values (1),(2),(3),(4),(5);
select sql_calc_found_rows a from t1 where a in (1,2,3) order by a desc limit 0,2;
select FOUND_ROWS();
select sql_calc_found_rows a from t1 where a in (1,2,3) order by a+2 desc limit 0,2;
select FOUND_ROWS();
drop table t1;

View file

@ -1,74 +0,0 @@
This directory contains all of the test cases for the MySQL Test Suite
marked up in XML.
To convert these test cases from XML into 'mysqltest' format, one needs
an XSL translator installed on their system. At MySQL, we use Sablotron
(http://www.gingerall.com/). Once installed, conversion happens with a
command like this:
sabcmd xsl/mysqltest.xsl < tests/sel000001.xml > sel000001.test
The file 'sel000001.test' contains the plain text conversion that is
to be fed into the 'mysqltest' program.
Below is an example of a test case marked up in XML; illustrating all
of the XML mark-up currently supported in our 'mysqltest.xsl' stylesheet.
----------------------------------------------------
<?xml version="1.0" standalone="no"?>
<!-- This file is maintained by matt@mysql.com -->
<test name="sel000001">
<version value="3.22"/>
<version value="3.23"/>
<description>This test will monkey around trying to kill mysqld.</description>
<connect name="Test_Connect1"
host="MyHostName"
user="Matt"
pass="MattPass"
db="MyDB"
port="3306"
sock="MyDB.sock"
/>
<connection name="Test_Connect1">
<resultfile name="sel000001.result">
<sql>SELECT y FROM foo WHERE bar='2'</sql>
</resultfile>
<sql>INSERT INTO foo VALUES (y='2') WHERE bar='1'</sql>
</connection>
</test>
----------------------------------------------------
The converted (mysqltest format) output of this source XML file looks
like:
----------------------------------------------------
# sel000001
#
# Versions
# --------
# 3.22
# 3.23
#
# Description
# -----------
# This test will monkey around trying to kill mysqld.
#
connect(Test_Connect1, MyHostName, Matt, MattPass, MyDB, 3306, MyDB.sock)
connection Test_Connect1
INSERT INTO foo VALUES (y='2') WHERE bar='1';
@sel000001.result SELECT y FROM foo WHERE bar='2';
----------------------------------------------------

View file

@ -1,21 +0,0 @@
<?xml version="1.0" standalone="no"?>
<!-- This file is maintained by matt@mysql.com -->
<test name="sel000001">
<version value="3.22"/>
<version value="3.23"/>
<description>This test is just a simple select.</description>
<description>Testing WHERE clause.</description>
<sql>DROP TABLE IF EXISTS t</sql>
<sql>CREATE TABLE t (s CHAR(20) PRIMARY KEY, id INT)</sql>
<sql>INSERT INTO t VALUES ('cat', 1), ('mouse', 3), ('dog', 2), ('snake', 77)</sql>
<resultfile name="r/3.23/sel000001.result">
<sql>SELECT s, id FROM t WHERE s = 'mouse'</sql>
</resultfile>
</test>

View file

@ -1,20 +0,0 @@
<?xml version="1.0" standalone="no"?>
<!-- This file is maintained by matt@mysql.com -->
<test name="sel000002">
<version value="3.22"/>
<version value="3.23"/>
<description>This test is just a simple select.</description>
<sql>DROP TABLE IF EXISTS t</sql>
<sql>CREATE TABLE t (n INT)</sql>
<sql>INSERT INTO t VALUES (1), (2), (3)</sql>
<resultfile name="r/3.23/sel000002.result">
<sql>SELECT * FROM t</sql>
</resultfile>
</test>

View file

@ -1,21 +0,0 @@
<?xml version="1.0" standalone="no"?>
<!-- This file is maintained by matt@mysql.com -->
<test name="sel000003">
<version value="3.22"/>
<version value="3.23"/>
<description>This test is just a simple select.</description>
<description>Testing count() function and GROUP BY clause.</description>
<sql>DROP TABLE IF EXISTS t</sql>
<sql>CREATE TABLE t (name CHAR(20) NOT NULL PRIMARY KEY, score SMALLINT NOT NULL, KEY(score))</sql>
<sql>INSERT INTO t VALUES ('Sasha', 20), ('Matt', 20), ('Monty', 10), ('David', 10), ('Tim', 10), ('Jeremy', 10)</sql>
<resultfile name="r/3.23/sel000003.result">
<sql>SELECT COUNT(*) as n, score FROM t GROUP BY score</sql>
</resultfile>
</test>

View file

@ -1,17 +0,0 @@
<?xml version="1.0" standalone="no"?>
<!-- This file is maintained by matt@mysql.com -->
<test name="sel000004">
<version value="3.22"/>
<version value="3.23"/>
<description>Simple arithmetic.</description>
<description>Testing MOD(), SIGN(), and arithmetic grouping.</description>
<resultfile name="r/3.23/sel000004.result">
<sql>SELECT 1+1,1-1,1+1*2,8/5,8%5,MOD(8,5),MOD(8,5)|0,-(1+1)*-2,SIGN(-5)</sql>
</resultfile>
</test>

View file

@ -1,17 +0,0 @@
<?xml version="1.0" standalone="no"?>
<!-- This file is maintained by matt@mysql.com -->
<test name="sel000005">
<version value="3.22"/>
<version value="3.23"/>
<description>Numeric functions.</description>
<description>Testing FLOOR(), CEILING(), ROUND().</description>
<resultfile name="r/3.23/sel000005.result">
<sql>SELECT FLOOR(5.5),FLOOR(-5.5),CEILING(5.5),CEILING(-5.5),ROUND(5.5),ROUND(-5.5)</sql>
</resultfile>
</test>

View file

@ -1,17 +0,0 @@
<?xml version="1.0" standalone="no"?>
<!-- This file is maintained by matt@mysql.com -->
<test name="sel000006">
<version value="3.22"/>
<version value="3.23"/>
<description>Numeric functions.</description>
<description>Testing ROUND(); hundreths precision.</description>
<resultfile name="r/3.23/sel000006.result">
<sql>SELECT ROUND(5.64,1),ROUND(5.64,2),ROUND(5.64,-1),ROUND(5.64,-2)</sql>
</resultfile>
</test>

View file

@ -1,17 +0,0 @@
<?xml version="1.0" standalone="no"?>
<!-- This file is maintained by matt@mysql.com -->
<test name="sel000007">
<version value="3.22"/>
<version value="3.23"/>
<description>Numeric functions.</description>
<description>Testing TRUNCATE().</description>
<resultfile name="r/3.23/sel000007.result">
<sql>SELECT TRUNCATE(52.64,1),TRUNCATE(52.64,2),TRUNCATE(52.64,-1),TRUNCATE(52.64,-2)</sql>
</resultfile>
</test>

View file

@ -1,17 +0,0 @@
<?xml version="1.0" standalone="no"?>
<!-- This file is maintained by matt@mysql.com -->
<test name="sel000008">
<version value="3.22"/>
<version value="3.23"/>
<description>Numeric functions.</description>
<description>Testing ABS(), LOG(), LOG10(), EXP(), SQRT(), POW(), RAND(), POWER().</description>
<resultfile name="r/3.23/sel000008.result">
<sql>SELECT ABS(-10),LOG(EXP(10)),EXP(LOG(SQRT(10))*2),POW(10,LOG10(10)),RAND(999999),RAND(),POWER(2,4)</sql>
</resultfile>
</test>

View file

@ -1,17 +0,0 @@
<?xml version="1.0" standalone="no"?>
<!-- This file is maintained by matt@mysql.com -->
<test name="sel000009">
<version value="3.22"/>
<version value="3.23"/>
<description>Numeric functions.</description>
<description>Testing PI(), SIN(), COS(), TAN(), COT(), ASIN(), ACOS(), ATAN().</description>
<resultfile name="r/3.23/sel000009.result">
<sql>SELECT PI(),SIN(PI()/2),COS(PI()/2),TAN(PI()),COT(1),ASIN(1),ACOS(0),ATAN(1)</sql>
</resultfile>
</test>

View file

@ -1,17 +0,0 @@
<?xml version="1.0" standalone="no"?>
<!-- This file is maintained by matt@mysql.com -->
<test name="sel000010">
<version value="3.22"/>
<version value="3.23"/>
<description>Numeric bitwise comparisons.</description>
<description>Testing |, &amp;, BIT_COUNT().</description>
<resultfile name="r/3.23/sel000010.result">
<sql>SELECT 1 | (1+1),5 &amp; 3,BIT_COUNT(7)</sql>
</resultfile>
</test>

View file

@ -1,17 +0,0 @@
<?xml version="1.0" standalone="no"?>
<!-- This file is maintained by matt@mysql.com -->
<test name="sel000011">
<version value="3.22"/>
<version value="3.23"/>
<description>Numeric bitmoving comparisons.</description>
<description>Testing &lt;&lt;, >>.</description>
<resultfile name="r/3.23/sel000011.result">
<sql>SELECT 1 &lt;&lt; 32,1 &lt;&lt; 63, 1 &lt;&lt; 64, 4 >> 2, 4 >> 63, 1&lt;&lt; 63 >> 60</sql>
</resultfile>
</test>

View file

@ -1,16 +0,0 @@
<?xml version="1.0" standalone="no"?>
<!-- This file is maintained by matt@mysql.com -->
<test name="sel000012">
<version value="3.22"/>
<version value="3.23"/>
<description>Numeric floating point.</description>
<resultfile name="r/3.23/sel000012.result">
<sql>SELECT 10,10.0,10.,.1e+2,100.0e-1</sql>
</resultfile>
</test>

View file

@ -1,16 +0,0 @@
<?xml version="1.0" standalone="no"?>
<!-- This file is maintained by matt@mysql.com -->
<test name="sel000013">
<version value="3.22"/>
<version value="3.23"/>
<description>Numeric floating point.</description>
<resultfile name="r/3.23/sel000013.result">
<sql>SELECT 6e-05, -6e-05, --6e-05, -6e-05+1.000000</sql>
</resultfile>
</test>

View file

@ -1,17 +0,0 @@
<?xml version="1.0" standalone="no"?>
<!-- This file is maintained by matt@mysql.com -->
<test name="sel000014">
<version value="3.22"/>
<version value="3.23"/>
<description>Numerics.</description>
<description>Testing pos/neg and zero padding.</description>
<resultfile name="r/3.23/sel000014.result">
<sql>SELECT 0,256,00000000000000065536,2147483647,-2147483648,2147483648,+4294967296</sql>
</resultfile>
</test>

View file

@ -1,17 +0,0 @@
<?xml version="1.0" standalone="no"?>
<!-- This file is maintained by matt@mysql.com -->
<test name="sel000015">
<version value="3.22"/>
<version value="3.23"/>
<description>Numerics.</description>
<description>Testing big numbers.</description>
<resultfile name="r/3.23/sel000015.result">
<sql>SELECT 922337203685477580,92233720368547758000</sql>
</resultfile>
</test>

View file

@ -1,17 +0,0 @@
<?xml version="1.0" standalone="no"?>
<!-- This file is maintained by matt@mysql.com -->
<test name="sel000016">
<version value="3.22"/>
<version value="3.23"/>
<description>Numerics.</description>
<description>Testing big negative numbers.</description>
<resultfile name="r/3.23/sel000016.result">
<sql>SELECT -922337203685477580,-92233720368547758000</sql>
</resultfile>
</test>

View file

@ -1,17 +0,0 @@
<?xml version="1.0" standalone="no"?>
<!-- This file is maintained by matt@mysql.com -->
<test name="sel000017">
<version value="3.22"/>
<version value="3.23"/>
<description>Numerics.</description>
<description>Testing big pos/neg numbers.</description>
<resultfile name="r/3.23/sel000017.result">
<sql>SELECT 9223372036854775807,-009223372036854775808</sql>
</resultfile>
</test>

View file

@ -1,17 +0,0 @@
<?xml version="1.0" standalone="no"?>
<!-- This file is maintained by matt@mysql.com -->
<test name="sel000018">
<version value="3.22"/>
<version value="3.23"/>
<description>Numerics.</description>
<description>Testing big pos/neg numbers.</description>
<resultfile name="r/3.23/sel000018.result">
<sql>SELECT +9999999999999999999,-9999999999999999999</sql>
</resultfile>
</test>

View file

@ -1,17 +0,0 @@
<?xml version="1.0" standalone="no"?>
<!-- This file is maintained by matt@mysql.com -->
<test name="sel000019">
<version value="3.22"/>
<version value="3.23"/>
<description>Numerics.</description>
<description>Testing DEGREES(), RADIANS().</description>
<resultfile name="r/3.23/sel000019.result">
<sql>SELECT DEGREES(PI()),RADIANS(360)</sql>
</resultfile>
</test>

View file

@ -1,17 +0,0 @@
<?xml version="1.0" standalone="no"?>
<!-- This file is maintained by matt@mysql.com -->
<test name="sel000020">
<version value="3.22"/>
<version value="3.23"/>
<description>Strings.</description>
<description>Testing string comparisons; STRCMP(), =, >, >=, &lt;=, !=.</description>
<resultfile name="r/3.23/sel000020.result">
<sql>SELECT 0=0,1>0,1>=1,1&lt;0,1&lt;=0,1!=0,STRCMP("abc","abcd"),STRCMP("b","a"),STRCMP("a","a")</sql>
</resultfile>
</test>

View file

@ -1,17 +0,0 @@
<?xml version="1.0" standalone="no"?>
<!-- This file is maintained by matt@mysql.com -->
<test name="sel000021">
<version value="3.22"/>
<version value="3.23"/>
<description>Strings.</description>
<description>Testing string comparisons; =, >, >=, &lt;=, &lt;>.</description>
<resultfile name="r/3.23/sel000021.result">
<sql>SELECT "a"&lt;"b","a"&lt;="b","b">="a","b">"a","a"="A","a"&lt;>"b"</sql>
</resultfile>
</test>

View file

@ -1,17 +0,0 @@
<?xml version="1.0" standalone="no"?>
<!-- This file is maintained by matt@mysql.com -->
<test name="sel000022">
<version value="3.22"/>
<version value="3.23"/>
<description>Strings.</description>
<description>Testing string comparisons; =, >, &lt;=.</description>
<resultfile name="r/3.23/sel000022.result">
<sql>SELECT "a "="A", "A "="a", "a " &lt;= "A b"</sql>
</resultfile>
</test>

View file

@ -1,17 +0,0 @@
<?xml version="1.0" standalone="no"?>
<!-- This file is maintained by matt@mysql.com -->
<test name="sel000023">
<version value="3.22"/>
<version value="3.23"/>
<description>Strings.</description>
<description>Testing string comparisons; LIKE, NOT LIKE, '%'.</description>
<resultfile name="r/3.23/sel000023.result">
<sql>SELECT "abc" LIKE "a%", "abc" NOT LIKE "%d%", "a%" LIKE "a\%","abc%" LIKE "a%\%","abcd" LIKE "a%b_%d", "a" LIKE "%%a","abcde" LIKE "a%_e","abc" LIKE "abc%"</sql>
</resultfile>
</test>

View file

@ -1,17 +0,0 @@
<?xml version="1.0" standalone="no"?>
<!-- This file is maintained by matt@mysql.com -->
<test name="sel000024">
<version value="3.22"/>
<version value="3.23"/>
<description>Strings.</description>
<description>Testing string comparisons; LIKE, '%'.</description>
<resultfile name="r/3.23/sel000024.result">
<sql>SELECT "a" LIKE "%%b","a" LIKE "%%ab","ab" LIKE "a\%", "ab" LIKE "_", "ab" LIKE "ab_", "abc" LIKE "%_d", "abc" LIKE "abc%d"</sql>
</resultfile>
</test>

View file

@ -1,17 +0,0 @@
<?xml version="1.0" standalone="no"?>
<!-- This file is maintained by matt@mysql.com -->
<test name="sel000025">
<version value="3.22"/>
<version value="3.23"/>
<description>Strings.</description>
<description>Testing string comparisons; LIKE, ESCAPE, '%'.</description>
<resultfile name="r/3.23/sel000025.result">
<sql>SELECT '?' LIKE '|%', '?' LIKE '|%' ESCAPE '|', '%' LIKE '|%', '%' LIKE '|%' ESCAPE '|', '%' LIKE '%'</sql>
</resultfile>
</test>

View file

@ -1,17 +0,0 @@
<?xml version="1.0" standalone="no"?>
<!-- This file is maintained by matt@mysql.com -->
<test name="sel000026">
<version value="3.22"/>
<version value="3.23"/>
<description>Strings.</description>
<description>Testing string comparisons; LIKE, '%'.</description>
<resultfile name="r/3.23/sel000026.result">
<sql>SELECT 'abc' LIKE '%c','abcabc' LIKE '%c', "ab" LIKE "", "ab" LIKE "a", "ab" LIKE "ab"</sql>
</resultfile>
</test>

View file

@ -1,17 +0,0 @@
<?xml version="1.0" standalone="no"?>
<!-- This file is maintained by matt@mysql.com -->
<test name="sel000027">
<version value="3.22"/>
<version value="3.23"/>
<description>Strings.</description>
<description>Testing string comparisons; REGEXP.</description>
<resultfile name="r/3.23/sel000027.result">
<sql>SELECT "Det här är svenska" REGEXP "h[[:alpha:]]+r", "aba" REGEXP "^(a|b)*$"</sql>
</resultfile>
</test>

View file

@ -1,17 +0,0 @@
<?xml version="1.0" standalone="no"?>
<!-- This file is maintained by matt@mysql.com -->
<test name="sel000028">
<version value="3.22"/>
<version value="3.23"/>
<description>Strings.</description>
<description>Testing string comparisons; REGEXP, CONCAT().</description>
<resultfile name="r/3.23/sel000028.result">
<sql>SELECT "aba" REGEXP CONCAT("^","a")</sql>
</resultfile>
</test>

View file

@ -1,17 +0,0 @@
<?xml version="1.0" standalone="no"?>
<!-- This file is maintained by matt@mysql.com -->
<test name="sel000029">
<version value="3.22"/>
<version value="3.23"/>
<description>Strings.</description>
<description>Testing string comparisons; NOT, AND, OR, !, &amp;&amp;, ||.</description>
<resultfile name="r/3.23/sel000029.result">
<sql>SELECT !0,NOT 0=1,!(0=0),1 AND 1,1 &amp;&amp; 0,0 OR 1,1 || NULL, 1=1 OR 1=1 AND 1=0</sql>
</resultfile>
</test>

View file

@ -1,17 +0,0 @@
<?xml version="1.0" standalone="no"?>
<!-- This file is maintained by matt@mysql.com -->
<test name="sel000030">
<version value="3.22"/>
<version value="3.23"/>
<description>Control flow.</description>
<description>Testing control flow; IF()</description>
<resultfile name="r/3.23/sel000030.result">
<sql>SELECT IF(0,"ERROR","this"),IF(1,"is","ERROR"),IF(NULL,"ERROR","a"),IF(1,2,3)|0,IF(1,2.0,3.0)+0</sql>
</resultfile>
</test>

View file

@ -1,4 +0,0 @@
XML Stylesheets for converting test cases in XML to other forms.
- mysqltest.xsl -> mysqltest format (text)

View file

@ -1,59 +0,0 @@
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:template match="/"><xsl:apply-templates /></xsl:template>
<!-- Main Template -->
<xsl:template match="/test"># <xsl:apply-templates select="@name"/>
#
# Versions
# --------<xsl:apply-templates select="version"/>
#
# Description
# -----------<xsl:apply-templates select="description"/>
#
<xsl:apply-templates select="connect"/>
<xsl:apply-templates select="connection"/>
<xsl:apply-templates select="sql"/>
<xsl:apply-templates select="resultfile"/>
</xsl:template>
<!-- End Main Template -->
<xsl:template match="version">
# <xsl:apply-templates select="@value"/>
</xsl:template>
<xsl:template match="description">
# <xsl:apply-templates />
</xsl:template>
<xsl:template match="connect">
connect(<xsl:apply-templates select="@name"/>, <xsl:apply-templates select="@host"/>, <xsl:apply-templates select="@user"/>, <xsl:apply-templates select="@pass"/>, <xsl:apply-templates select="@db"/>, <xsl:apply-templates select="@port"/>, <xsl:apply-templates select="@sock"/>)
</xsl:template>
<xsl:template match="connection">
<xsl:text>
connection </xsl:text><xsl:apply-templates select="@name"/>
<xsl:text>
</xsl:text>
<xsl:apply-templates select="sql"/>
<xsl:apply-templates select="resultfile"/>
</xsl:template>
<xsl:template match="resultfile">@<xsl:apply-templates select="@name"/><xsl:text> </xsl:text><xsl:apply-templates select="sql"/>
</xsl:template>
<xsl:template match="sql">
<xsl:apply-templates />;
</xsl:template>
</xsl:stylesheet>

View file

@ -29,8 +29,15 @@ static my_bool compare_strings (register const char *s, register const char *t,
static longlong getopt_ll (char *arg, const struct my_option *optp, int *err);
static void init_variables(const struct my_option *options);
#define DISABLE_OPTION_COUNT 2
static const char *special_opt_prefix[]=
{"skip", "disable", "enable", "maximum", 0};
/* Return error values from handle_options */
#define ERR_UNKNOWN_OPTION 1
#define ERR_AMBIGUOUS_OPTION 2
#define ERR_NO_ARGUMENT_ALLOWED 3
@ -41,9 +48,6 @@ static void init_variables(const struct my_option *options);
#define ERR_UNKNOWN_SUFFIX 8
#define ERR_NO_PTR_TO_VARIABLE 9
static const char *special_opt_prefix[]=
{"skip", "disable", "enable", "maximum", 0};
/*
function: handle_options
@ -63,95 +67,91 @@ int handle_options(int *argc, char ***argv,
{
uint opt_found, argvpos= 0, length, spec_len, i;
int err;
my_bool end_of_options= 0, must_be_var, set_maximum_value;
my_bool end_of_options= 0, must_be_var, set_maximum_value, special_used;
char *progname= *(*argv), **pos, *optend, *prev_found;
const struct my_option *optp;
LINT_INIT(opt_found);
(*argc)--; /* Skip the program name */
(*argv)++; /* --- || ---- */
init_variables(longopts);
for (pos= *argv; *pos; pos++)
{
char *cur_arg= *pos;
if (*cur_arg == '-' && *(cur_arg + 1) && !end_of_options) /* must be opt */
if (cur_arg[0] == '-' && cur_arg[1] && !end_of_options) /* must be opt */
{
char *argument= 0;
must_be_var= 0;
char *argument= 0;
must_be_var= 0;
set_maximum_value= 0;
special_used= 0;
/* check for long option, or --set-variable (-O) */
if (*(cur_arg + 1) == '-' || *(cur_arg + 1) == 'O')
cur_arg++; /* skip '-' */
if (*cur_arg == 'O')
{
if (*(cur_arg + 1) == 'O' ||
!compare_strings(cur_arg, "--set-variable", 14))
must_be_var= 1;
if (!(*++cur_arg)) /* If not -Ovar=# */
{
/* the argument must be in next argv */
if (!*++pos)
{
fprintf(stderr, "%s: Option '-O' requires an argument\n",
progname);
return ERR_ARGUMENT_REQUIRED;
}
cur_arg= *pos;
(*argc)--;
}
}
else if (*cur_arg == '-') /* check for long option, or --set-variable */
{
if (!compare_strings(cur_arg, "-set-variable", 13))
{
must_be_var= 1;
if (*(cur_arg + 1) == 'O')
{
cur_arg+= 2;
if (!(*cur_arg))
{
/* the argument must be in next argv */
if (!(*(pos + 1)))
{
fprintf(stderr, "%s: Option '-O' requires an argument\n",
progname);
return ERR_ARGUMENT_REQUIRED;
}
pos++;
cur_arg= *pos;
(*argc)--;
}
}
else /* Option argument begins with string '--set-variable' */
if (cur_arg[13] == '=')
{
cur_arg+= 14;
if (*cur_arg == '=')
if (!*cur_arg)
{
cur_arg++;
if (!(*cur_arg))
{
fprintf(stderr,
"%s: Option '--set-variable' requires an argument\n",
progname);
return ERR_ARGUMENT_REQUIRED;
}
fprintf(stderr,
"%s: Option '--set-variable' requires an argument\n",
progname);
return ERR_ARGUMENT_REQUIRED;
}
else if (*cur_arg) /* garbage, or another option. break out */
}
else if (cur_arg[14]) /* garbage, or another option. break out */
must_be_var= 0;
else
{
/* the argument must be in next argv */
if (!*++pos)
{
cur_arg-= 14;
must_be_var= 0;
}
else
{
/* the argument must be in next argv */
if (!(*(pos + 1)))
{
fprintf(stderr,
"%s: Option '--set-variable' requires an argument\n",
progname);
return ERR_ARGUMENT_REQUIRED;
}
pos++;
cur_arg= *pos;
(*argc)--;
fprintf(stderr,
"%s: Option '--set-variable' requires an argument\n",
progname);
return ERR_ARGUMENT_REQUIRED;
}
cur_arg= *pos;
(*argc)--;
}
}
else if (!must_be_var)
{
/* '--' means end of options, look no further */
if (!*(cur_arg + 2))
if (!*++cur_arg) /* skip the double dash */
{
/* '--' means end of options, look no further */
end_of_options= 1;
(*argc)--;
continue;
}
cur_arg+= 2; /* skip the double dash */
}
for (optend= cur_arg; *optend && *optend != '='; optend++) ;
optend= strcend(cur_arg, '=');
length= optend - cur_arg;
if (*optend == '=')
optend++;
else
optend=0;
/*
Find first the right option. Return error in case of an ambiguous,
or unknown option
@ -165,7 +165,7 @@ int handle_options(int *argc, char ***argv,
*/
if (!must_be_var)
{
if (*optend == '=')
if (optend)
must_be_var= 1;
for (i= 0; special_opt_prefix[i]; i++)
{
@ -176,6 +176,7 @@ int handle_options(int *argc, char ***argv,
/*
We were called with a special prefix, we can reuse opt_found
*/
special_used= 1;
cur_arg += (spec_len + 1);
if ((opt_found= findopt(cur_arg, length - (spec_len + 1),
&optp, &prev_found)))
@ -189,9 +190,9 @@ int handle_options(int *argc, char ***argv,
return ERR_AMBIGUOUS_OPTION;
}
if (i < DISABLE_OPTION_COUNT)
optend= (char*) "=0";
optend= (char*) "0";
else if (!compare_strings(special_opt_prefix[i],"enable",6))
optend= (char*) "=1";
optend= (char*) "1";
else if (!compare_strings(special_opt_prefix[i],"maximum",7))
{
set_maximum_value= 1;
@ -233,81 +234,81 @@ int handle_options(int *argc, char ***argv,
return ERR_AMBIGUOUS_OPTION;
}
}
if (must_be_var && !optp->opt_is_var)
if (must_be_var && !optp->value)
{
fprintf(stderr, "%s: the argument '%s' is not an variable\n",
progname, *pos);
return ERR_MUST_BE_VARIABLE;
}
if (optp->arg_type == NO_ARG && *optend == '=')
if (optp->arg_type == NO_ARG && optend && !special_used)
{
fprintf(stderr, "%s: option '--%s' cannot take an argument\n",
progname, optp->name);
return ERR_NO_ARGUMENT_ALLOWED;
}
else if (optp->arg_type == REQUIRED_ARG && !*optend)
else if (optp->arg_type == REQUIRED_ARG && !optend)
{
/* Check if there are more arguments after this one */
if (!(*(pos + 1)))
if (!*++pos)
{
fprintf(stderr, "%s: option '--%s' requires an argument\n",
progname, optp->name);
return ERR_ARGUMENT_REQUIRED;
}
pos++;
argument= *pos;
(*argc)--;
}
else if (*optend == '=')
argument= *(optend + 1) ? optend + 1 : (char*) "";
else
argument= optend;
}
else /* must be short option */
{
my_bool skip;
for (skip= 0, optend= (cur_arg + 1); *optend && !skip; optend++)
for (optend= cur_arg; *optend; optend++, opt_found= 0)
{
for (optp= longopts; optp->id ; optp++)
for (optp= longopts; optp->id; optp++)
{
if (optp->id == (int) (uchar) *optend)
{
/* Option recognized. Find next what to do with it */
opt_found= 1;
if (optp->arg_type == REQUIRED_ARG || optp->arg_type == OPT_ARG)
{
if (*(optend + 1))
{
argument= (optend + 1);
/*
The rest of the option is option argument
This is in effect a jump out of this loop
*/
skip= 1;
// The rest of the option is option argument
argument= optend + 1;
// This is in effect a jump out of the outer loop
optend= (char*) " ";
}
else if (optp->arg_type == REQUIRED_ARG)
{
/* Check if there are more arguments after this one */
if (!(*(pos + 1)))
if (!*++pos)
{
fprintf(stderr, "%s: option '-%c' requires an argument\n",
progname, optp->id);
return ERR_ARGUMENT_REQUIRED;
}
pos++;
argument= *pos;
(*argc)--;
/* the other loop will break, because *optend + 1 == 0 */
}
}
else
{
/* we are hitting many options in 1 argv */
if (*(optend + 1))
get_one_option(optp->id, optp, 0);
}
get_one_option(optp->id, optp, argument);
break;
}
}
if (!opt_found)
{
fprintf(stderr,
"%s: unknown option '-%c'\n", progname, *cur_arg);
return ERR_UNKNOWN_OPTION;
}
}
(*argc)--; /* option handled (short), decrease argument count */
continue;
}
if (optp->opt_is_var)
if (optp->value)
{
gptr *result_pos= (set_maximum_value) ?
optp->u_max_value : optp->value;
@ -349,6 +350,7 @@ int handle_options(int *argc, char ***argv,
list the option found, if any. In case of ambiguous option, store
the name in ffname argument
*/
static int findopt (char *optpat, uint length,
const struct my_option **opt_res,
char **ffname)
@ -378,6 +380,7 @@ static int findopt (char *optpat, uint length,
Works like strncmp, other than 1.) considers '-' and '_' the same.
2.) Returns -1 if strings differ, 0 if they are equal
*/
static my_bool compare_strings(register const char *s, register const char *t,
uint length)
{
@ -401,6 +404,7 @@ static my_bool compare_strings(register const char *s, register const char *t,
that those values are honored.
In case of an error, set error value in *err.
*/
static longlong getopt_ll (char *arg, const struct my_option *optp, int *err)
{
char *endchar;
@ -423,11 +427,14 @@ static longlong getopt_ll (char *arg, const struct my_option *optp, int *err)
}
if (num < (longlong) optp->min_value)
num= (longlong) optp->min_value;
else if (num > 0 && (ulonglong) num > (ulonglong) (ulong) optp->max_value)
else if (num > 0 && (ulonglong) num > (ulonglong) (ulong) optp->max_value
&& optp->max_value) // if max value is not set -> no upper limit
num= (longlong) (ulong) optp->max_value;
num= ((num - (longlong) optp->sub_size) / (ulonglong) optp->block_size);
return (longlong) (num * (ulonglong) optp->block_size);
num= ((num - (longlong) optp->sub_size) / (optp->block_size ?
(ulonglong) optp->block_size :
1L));
return (longlong) (num * (optp->block_size ? (ulonglong) optp->block_size :
1L));
}
@ -436,11 +443,12 @@ static longlong getopt_ll (char *arg, const struct my_option *optp, int *err)
initialize all variables to their default values
*/
static void init_variables(const struct my_option *options)
{
for ( ; options->name ; options++)
for (; options->name; options++)
{
if (options->opt_is_var)
if (options->value)
{
if (options->var_type == GET_LONG)
*((long*) options->u_max_value)= *((long*) options->value)=
@ -451,3 +459,120 @@ static void init_variables(const struct my_option *options)
}
}
}
/*
function: my_print_options
Print help for all options and variables.
*/
void my_print_help(const struct my_option *options)
{
uint col, name_space= 22, comment_space= 57;
const char *line_end;
const struct my_option *optp;
for (optp= options; optp->id; optp++)
{
if (optp->id < 256)
{
printf(" -%c, ", optp->id);
col= 6;
}
else
{
printf(" ");
col= 2;
}
printf("--%s", optp->name);
col+= 2 + strlen(optp->name);
if (optp->var_type == GET_STR)
{
printf("=name ");
col+= 6;
}
else if (optp->var_type == GET_NO_ARG)
{
putchar(' ');
col++;
}
else
{
printf("=# ");
col+= 3;
}
if (col > name_space)
{
putchar('\n');
col= 0;
}
for (; col < name_space; col++)
putchar(' ');
if (optp->comment && *optp->comment)
{
const char *comment= optp->comment, *end= strend(comment);
while ((uint) (end - comment) > comment_space)
{
for (line_end= comment + comment_space; *line_end != ' '; line_end--);
for (; comment != line_end; comment++)
putchar(*comment);
comment++; // skip the space, as a newline will take it's place now
putchar('\n');
for (col= 0; col < name_space; col++)
putchar(' ');
}
printf("%s", comment);
}
putchar('\n');
}
}
/*
function: my_print_options
Print variables.
*/
void my_print_variables(const struct my_option *options)
{
uint name_space= 34, length;
char buff[255];
const struct my_option *optp;
printf("Variables (--variable-name=value) Default value\n");
printf("--------------------------------- -------------\n");
for (optp= options; optp->id; optp++)
{
if (optp->value)
{
printf("%s", optp->name);
length= strlen(optp->name);
for (; length < name_space; length++)
putchar(' ');
if (optp->var_type == GET_STR)
{
if (!optp->def_value && !*((char**) optp->value))
printf("(No default value)\n");
else
printf("%s\n", *((char**) optp->value));
}
else if (optp->var_type == GET_LONG)
{
if (!optp->def_value && !*((long*) optp->value))
printf("(No default value)\n");
else
printf("%lu\n", *((long*) optp->value));
}
else
{
if (!optp->def_value && !*((longlong*) optp->value))
printf("(No default value)\n");
else
printf("%s\n", llstr(*((longlong*) optp->value), buff));
}
}
}
}

View file

@ -45,6 +45,7 @@ static int NEAR_F delete_file(const char *name,const char *ext,int extflag);
ulong ha_read_count, ha_write_count, ha_delete_count, ha_update_count,
ha_read_key_count, ha_read_next_count, ha_read_prev_count,
ha_read_first_count, ha_read_last_count,
ha_commit_count, ha_rollback_count,
ha_read_rnd_count, ha_read_rnd_next_count;
const char *ha_table_type[] = {
@ -267,6 +268,7 @@ int ha_commit_trans(THD *thd, THD_TRANS* trans)
#ifdef USING_TRANSACTIONS
if (opt_using_transactions)
{
bool operation_done=0;
/* Update the binary log if we have cached some queries */
if (trans == &thd->transaction.all && mysql_bin_log.is_open() &&
my_b_tell(&thd->transaction.trans_log))
@ -297,12 +299,17 @@ int ha_commit_trans(THD *thd, THD_TRANS* trans)
}
trans->innodb_active_trans=0;
if (trans == &thd->transaction.all)
{
query_cache.invalidate(Query_cache_table::INNODB);
operation_done=1;
}
}
#endif
if (error && trans == &thd->transaction.all && mysql_bin_log.is_open())
sql_print_error("Error: Got error during commit; Binlog is not up to date!");
thd->tx_isolation=thd->session_tx_isolation;
if (operation_done)
statistic_increment(ha_commit_count,&LOCK_status);
}
#endif // using transactions
DBUG_RETURN(error);
@ -316,6 +323,7 @@ int ha_rollback_trans(THD *thd, THD_TRANS *trans)
#ifdef USING_TRANSACTIONS
if (opt_using_transactions)
{
bool operation_done=0;
#ifdef HAVE_BERKELEY_DB
if (trans->bdb_tid)
{
@ -325,6 +333,7 @@ int ha_rollback_trans(THD *thd, THD_TRANS *trans)
error=1;
}
trans->bdb_tid=0;
operation_done=1;
}
#endif
#ifdef HAVE_INNOBASE_DB
@ -336,6 +345,7 @@ int ha_rollback_trans(THD *thd, THD_TRANS *trans)
error=1;
}
trans->innodb_active_trans=0;
operation_done=1;
}
#endif
if (trans == &thd->transaction.all)
@ -343,6 +353,8 @@ int ha_rollback_trans(THD *thd, THD_TRANS *trans)
WRITE_CACHE, (my_off_t) 0, 0, 1);
thd->transaction.trans_log.end_of_file= max_binlog_cache_size;
thd->tx_isolation=thd->session_tx_isolation;
if (operation_done)
statistic_increment(ha_rollback_count,&LOCK_status);
}
#endif /* USING_TRANSACTIONS */
DBUG_RETURN(error);

View file

@ -556,6 +556,8 @@ Log_event* Log_event::read_log_event(const char* buf, int event_len,
ev = new Query_log_event(buf, event_len, old_format);
break;
case LOAD_EVENT:
ev = new Create_file_log_event(buf, event_len, old_format);
break;
case NEW_LOAD_EVENT:
ev = new Load_log_event(buf, event_len, old_format);
break;
@ -566,7 +568,7 @@ Log_event* Log_event::read_log_event(const char* buf, int event_len,
ev = new Slave_log_event(buf, event_len);
break;
case CREATE_FILE_EVENT:
ev = new Create_file_log_event(buf, event_len);
ev = new Create_file_log_event(buf, event_len, old_format);
break;
case APPEND_BLOCK_EVENT:
ev = new Append_block_log_event(buf, event_len);
@ -959,6 +961,12 @@ char* sql_ex_info::init(char* buf,char* buf_end,bool use_new_format)
if (use_new_format)
{
empty_flags=0;
/* the code below assumes that buf will not disappear from
under our feet during the lifetime of the event. This assumption
holds true in the slave thread if the log is in new format, but is not
the case when we have old format because we will be reusing net buffer
to read the actual file before we write out the Create_file event
*/
if (read_str(buf, buf_end, field_term, field_term_len) ||
read_str(buf, buf_end, enclosed, enclosed_len) ||
read_str(buf, buf_end, line_term, line_term_len) ||
@ -970,11 +978,11 @@ char* sql_ex_info::init(char* buf,char* buf_end,bool use_new_format)
else
{
field_term_len= enclosed_len= line_term_len= line_start_len= escaped_len=1;
*field_term=*buf++;
*enclosed= *buf++;
*line_term= *buf++;
*line_start=*buf++;
*escaped= *buf++;
field_term = buf++;
enclosed= buf++;
line_term= buf++;
line_start= buf++;
escaped= buf++;
opt_flags = *buf++;
empty_flags=*buf++;
if (empty_flags & FIELD_TERM_EMPTY)
@ -1095,7 +1103,9 @@ int Load_log_event::copy_log_event(const char *buf, ulong event_len,
db_len = (uint)data_head[L_DB_LEN_OFFSET];
num_fields = uint4korr(data_head + L_NUM_FIELDS_OFFSET);
int body_offset = get_data_body_offset();
int body_offset = (buf[EVENT_TYPE_OFFSET] == LOAD_EVENT) ?
LOAD_HEADER_LEN + OLD_HEADER_LEN : get_data_body_offset();
if ((int) event_len < body_offset)
return 1;
//sql_ex.init() on success returns the pointer to the first byte after
@ -1117,7 +1127,6 @@ int Load_log_event::copy_log_event(const char *buf, ulong event_len,
table_name = fields + field_block_len;
db = table_name + table_name_len + 1;
fname = db + db_len + 1;
int type_code = get_type_code();
fname_len = strlen(fname);
// null termination is accomplished by the caller doing buf[event_len]=0
return 0;
@ -1367,20 +1376,29 @@ int Create_file_log_event::write_base(IO_CACHE* file)
return res;
}
Create_file_log_event::Create_file_log_event(const char* buf, int len):
Load_log_event(buf,0,0),fake_base(0),block(0)
Create_file_log_event::Create_file_log_event(const char* buf, int len,
bool old_format):
Load_log_event(buf,0,old_format),fake_base(0),block(0),inited_from_old(0)
{
int block_offset;
if (copy_log_event(buf,len,0))
if (copy_log_event(buf,len,old_format))
return;
file_id = uint4korr(buf + LOG_EVENT_HEADER_LEN +
+ LOAD_HEADER_LEN + CF_FILE_ID_OFFSET);
block_offset = LOG_EVENT_HEADER_LEN + Load_log_event::get_data_size() +
CREATE_FILE_HEADER_LEN + 1; // 1 for \0 terminating fname
if (len < block_offset)
return;
block = (char*)buf + block_offset;
block_len = len - block_offset;
if (!old_format)
{
file_id = uint4korr(buf + LOG_EVENT_HEADER_LEN +
+ LOAD_HEADER_LEN + CF_FILE_ID_OFFSET);
block_offset = LOG_EVENT_HEADER_LEN + Load_log_event::get_data_size() +
CREATE_FILE_HEADER_LEN + 1; // 1 for \0 terminating fname
if (len < block_offset)
return;
block = (char*)buf + block_offset;
block_len = len - block_offset;
}
else
{
sql_ex.force_new_format();
inited_from_old = 1;
}
}
@ -1568,6 +1586,7 @@ int Query_log_event::exec_event(struct st_relay_log_info* rli)
int expected_error,actual_error = 0;
init_sql_alloc(&thd->mem_root, 8192,0);
thd->db = rewrite_db((char*)db);
DBUG_ASSERT(q_len == strlen(query));
if (db_ok(thd->db, replicate_do_db, replicate_ignore_db))
{
thd->query = (char*)query;
@ -1739,11 +1758,12 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli)
int Start_log_event::exec_event(struct st_relay_log_info* rli)
{
close_temporary_tables(thd);
// if we have old format, load_tmpdir is cleaned up by the I/O thread
// TODO: cleanup_load_tmpdir() needs to remove only the files associated
// with the server id that has just started
if (!rli->mi->old_format)
{
close_temporary_tables(thd);
cleanup_load_tmpdir();
}
return Log_event::exec_event(rli);
}

View file

@ -64,6 +64,8 @@ struct old_sql_ex
char empty_flags;
};
#define NUM_LOAD_DELIM_STRS 5
struct sql_ex_info
{
@ -153,8 +155,8 @@ struct sql_ex_info
#define L_THREAD_ID_OFFSET 0
#define L_EXEC_TIME_OFFSET 4
#define L_SKIP_LINES_OFFSET 8
#define L_DB_LEN_OFFSET 12
#define L_TBL_LEN_OFFSET 13
#define L_TBL_LEN_OFFSET 12
#define L_DB_LEN_OFFSET 13
#define L_NUM_FIELDS_OFFSET 14
#define L_SQL_EX_OFFSET 18
#define L_DATA_OFFSET LOAD_HEADER_LEN
@ -570,6 +572,7 @@ public:
char* block;
uint block_len;
uint file_id;
bool inited_from_old;
#ifndef MYSQL_CLIENT
Create_file_log_event(THD* thd, sql_exchange* ex, const char* db_arg,
const char* table_name_arg,
@ -578,7 +581,7 @@ public:
char* block_arg, uint block_len_arg);
#endif
Create_file_log_event(const char* buf, int event_len);
Create_file_log_event(const char* buf, int event_len, bool old_format);
~Create_file_log_event()
{
}
@ -591,7 +594,7 @@ public:
4 + 1 + block_len;}
int get_data_body_offset() { return fake_base ? LOAD_EVENT_OVERHEAD:
LOAD_EVENT_OVERHEAD + CREATE_FILE_HEADER_LEN; }
bool is_valid() { return block != 0; }
bool is_valid() { return inited_from_old || block != 0; }
int write_data_header(IO_CACHE* file);
int write_data_body(IO_CACHE* file);
int write_base(IO_CACHE* file); // cut out Create_file extentions and

View file

@ -48,6 +48,7 @@ char *sql_strmake(const char *str,uint len);
gptr sql_memdup(const void * ptr,unsigned size);
void sql_element_free(void *ptr);
void kill_one_thread(THD *thd, ulong id);
int net_request_file(NET* net, const char* fname);
char* query_table_status(THD *thd,const char *db,const char *table_name);
#define x_free(A) { my_free((gptr) (A),MYF(MY_WME | MY_FAE | MY_ALLOW_ZERO_PTR)); }
@ -586,7 +587,8 @@ extern char f_fyllchar;
extern ulong ha_read_count, ha_write_count, ha_delete_count, ha_update_count,
ha_read_key_count, ha_read_next_count, ha_read_prev_count,
ha_read_first_count, ha_read_last_count,
ha_read_rnd_count, ha_read_rnd_next_count;
ha_read_rnd_count, ha_read_rnd_next_count,
ha_commit_count, ha_rollback_count;
extern MY_BITMAP temp_pool;
extern uchar *days_in_month;
extern DATE_FORMAT dayord;

View file

@ -3068,7 +3068,7 @@ struct show_var_st init_vars[]= {
{"log_update", (char*) &opt_update_log, SHOW_BOOL},
{"log_bin", (char*) &opt_bin_log, SHOW_BOOL},
{"log_slave_updates", (char*) &opt_log_slave_updates, SHOW_BOOL},
{"log_long_queries", (char*) &opt_slow_log, SHOW_BOOL},
{"log_slow_queries", (char*) &opt_slow_log, SHOW_BOOL},
{"long_query_time", (char*) &long_query_time, SHOW_LONG},
{"low_priority_updates", (char*) &low_priority_updates, SHOW_BOOL},
{"lower_case_table_names", (char*) &lower_case_table_names, SHOW_LONG},
@ -3211,6 +3211,7 @@ struct show_var_st status_vars[]= {
{"Delayed_writes", (char*) &delayed_insert_writes, SHOW_LONG},
{"Delayed_errors", (char*) &delayed_insert_errors, SHOW_LONG},
{"Flush_commands", (char*) &refresh_version, SHOW_LONG_CONST},
{"Handler_commit", (char*) &ha_commit_count, SHOW_LONG},
{"Handler_delete", (char*) &ha_delete_count, SHOW_LONG},
{"Handler_read_first", (char*) &ha_read_first_count, SHOW_LONG},
{"Handler_read_key", (char*) &ha_read_key_count, SHOW_LONG},
@ -3218,6 +3219,7 @@ struct show_var_st status_vars[]= {
{"Handler_read_prev", (char*) &ha_read_prev_count, SHOW_LONG},
{"Handler_read_rnd", (char*) &ha_read_rnd_count, SHOW_LONG},
{"Handler_read_rnd_next", (char*) &ha_read_rnd_next_count, SHOW_LONG},
{"Handler_rollback", (char*) &ha_rollback_count, SHOW_LONG},
{"Handler_update", (char*) &ha_update_count, SHOW_LONG},
{"Handler_write", (char*) &ha_write_count, SHOW_LONG},
{"Key_blocks_used", (char*) &_my_blocks_used, SHOW_LONG_CONST},

View file

@ -814,3 +814,14 @@ my_net_read(NET *net)
#endif /* HAVE_COMPRESS */
return len;
}
int net_request_file(NET* net, const char* fname)
{
char tmp [FN_REFLEN+1],*end;
DBUG_ENTER("net_request_file");
tmp[0] = (char) 251; /* NULL_LENGTH */
end=strnmov(tmp+1,fname,sizeof(tmp)-2);
DBUG_RETURN(my_net_write(net,tmp,(uint) (end-tmp)) ||
net_flush(net));
}

View file

@ -828,6 +828,7 @@ int load_master_data(THD* thd)
active_mi->rli.master_log_pos = active_mi->master_log_pos;
strnmov(active_mi->rli.master_log_name,active_mi->master_log_name,
sizeof(active_mi->rli.master_log_name));
flush_relay_log_info(&active_mi->rli);
pthread_cond_broadcast(&active_mi->rli.data_cond);
pthread_mutex_unlock(&active_mi->rli.data_lock);
thd->proc_info = "starting slave";

View file

@ -55,6 +55,7 @@ typedef enum { SLAVE_THD_IO, SLAVE_THD_SQL} SLAVE_THD_TYPE;
void skip_load_data_infile(NET* net);
static int process_io_rotate(MASTER_INFO* mi, Rotate_log_event* rev);
static int process_io_create_file(MASTER_INFO* mi, Create_file_log_event* cev);
static int queue_old_event(MASTER_INFO* mi, const char* buf,
uint event_len);
static inline bool slave_killed(THD* thd,MASTER_INFO* mi);
@ -654,7 +655,7 @@ char* rewrite_db(char* db)
int db_ok(const char* db, I_List<i_string> &do_list,
I_List<i_string> &ignore_list )
{
if(do_list.is_empty() && ignore_list.is_empty())
if (do_list.is_empty() && ignore_list.is_empty())
return 1; // ok to replicate if the user puts no constraints
// if the user has specified restrictions on which databases to replicate
@ -1058,6 +1059,8 @@ int init_master_info(MASTER_INFO* mi, const char* master_info_fname,
if (init_relay_log_info(&mi->rli, slave_info_fname))
return 1;
mi->rli.mi = mi;
mi->mysql=0;
mi->file_id=1;
mi->ignore_stop_event=0;
int fd,error;
MY_STAT stat_area;
@ -1535,10 +1538,6 @@ static int exec_relay_log_event(THD* thd, RELAY_LOG_INFO* rli)
if (ev->server_id == ::server_id ||
(rli->slave_skip_counter && type_code != ROTATE_EVENT))
{
/*
TODO: I/O thread must handle skipping file delivery for
old load data infile events
*/
/* TODO: I/O thread should not even log events with the same server id */
rli->inc_pos(ev->get_event_len(),
type_code != STOP_EVENT ? ev->log_pos : LL(0),
@ -1621,7 +1620,7 @@ slave_begin:
DBUG_PRINT("info",("master info: log_file_name=%s, position=%s",
mi->master_log_name, llstr(mi->master_log_pos,llbuff)));
if (!(mysql = mc_mysql_init(NULL)))
if (!(mi->mysql = mysql = mc_mysql_init(NULL)))
{
sql_print_error("Slave I/O thread: error in mc_mysql_init()");
goto err;
@ -1780,8 +1779,11 @@ err:
sql_print_error("Slave I/O thread exiting, read up to log '%s', position %s",
IO_RPL_LOG_NAME, llstr(mi->master_log_pos,llbuff));
thd->query = thd->db = 0; // extra safety
if(mysql)
if (mysql)
{
mc_mysql_close(mysql);
mi->mysql=0;
}
thd->proc_info = "Waiting for slave mutex on exit";
pthread_mutex_lock(&mi->run_lock);
mi->slave_running = 0;
@ -1790,7 +1792,7 @@ err:
change_rpl_status(RPL_ACTIVE_SLAVE,RPL_IDLE_SLAVE);
mi->abort_slave = 0; // TODO: check if this is needed
DBUG_ASSERT(thd->net.buff != 0);
net_end(&thd->net); // destructor will not free it, because we are weird
net_end(&thd->net); // destructor will not free it, because net.vio is 0
pthread_mutex_lock(&LOCK_thread_count);
delete thd;
pthread_mutex_unlock(&LOCK_thread_count);
@ -1926,11 +1928,101 @@ the slave SQL thread with \"SLAVE START\". We stopped at log \
DBUG_RETURN(0); // Can't return anything here
}
static int process_io_create_file(MASTER_INFO* mi, Create_file_log_event* cev)
{
int error = 1;
ulong num_bytes;
bool cev_not_written;
THD* thd;
NET* net = &mi->mysql->net;
if (unlikely(!cev->is_valid()))
return 1;
/*
TODO: fix to honor table rules, not only db rules
*/
if (!db_ok(cev->db, replicate_do_db, replicate_ignore_db))
{
skip_load_data_infile(net);
return 0;
}
DBUG_ASSERT(cev->inited_from_old);
thd = mi->io_thd;
thd->file_id = cev->file_id = mi->file_id++;
thd->server_id = cev->server_id;
cev_not_written = 1;
if (unlikely(net_request_file(net,cev->fname)))
{
sql_print_error("Slave I/O: failed requesting download of '%s'",
cev->fname);
goto err;
}
/* this dummy block is so we could insantiate Append_block_log_event
once and then modify it slightly instead of doing it multiple times
in the loop
*/
{
Append_block_log_event aev(thd,0,0);
for (;;)
{
if (unlikely((num_bytes=my_net_read(net)) == packet_error))
{
sql_print_error("Network read error downloading '%s' from master",
cev->fname);
goto err;
}
if (unlikely(!num_bytes)) /* eof */
{
send_ok(net); /* 3.23 master wants it */
Execute_load_log_event xev(thd);
xev.log_pos = mi->master_log_pos;
if (unlikely(mi->rli.relay_log.append(&xev)))
{
sql_print_error("Slave I/O: error writing Exec_load event to \
relay log");
goto err;
}
break;
}
if (unlikely(cev_not_written))
{
cev->block = (char*)net->read_pos;
cev->block_len = num_bytes;
cev->log_pos = mi->master_log_pos;
if (unlikely(mi->rli.relay_log.append(cev)))
{
sql_print_error("Slave I/O: error writing Create_file event to \
relay log");
goto err;
}
cev_not_written=0;
}
else
{
aev.block = (char*)net->read_pos;
aev.block_len = num_bytes;
aev.log_pos = mi->master_log_pos;
if (unlikely(mi->rli.relay_log.append(&aev)))
{
sql_print_error("Slave I/O: error writing Append_block event to \
relay log");
goto err;
}
}
}
}
error=0;
err:
return error;
}
// We assume we already locked mi->data_lock
static int process_io_rotate(MASTER_INFO* mi, Rotate_log_event* rev)
{
if (!rev->is_valid())
if (unlikely(!rev->is_valid()))
return 1;
DBUG_ASSERT(rev->ident_len<sizeof(mi->master_log_name));
memcpy(mi->master_log_name,rev->new_log_ident,
@ -1961,6 +2053,21 @@ static int queue_old_event(MASTER_INFO *mi, const char *buf,
const char *errmsg = 0;
bool inc_pos = 1;
bool processed_stop_event = 0;
char* tmp_buf = 0;
/* if we get Load event, we need to pass a non-reusable buffer
to read_log_event, so we do a trick
*/
if (buf[EVENT_TYPE_OFFSET] == LOAD_EVENT)
{
if (unlikely(!(tmp_buf=(char*)my_malloc(event_len+1,MYF(MY_WME)))))
{
sql_print_error("Slave I/O: out of memory for Load event");
return 1;
}
memcpy(tmp_buf,buf,event_len);
tmp_buf[event_len]=0; // Create_file constructor wants null-term buffer
buf = (const char*)tmp_buf;
}
Log_event *ev = Log_event::read_log_event(buf,event_len, &errmsg,
1 /*old format*/ );
if (unlikely(!ev))
@ -1968,6 +2075,7 @@ static int queue_old_event(MASTER_INFO *mi, const char *buf,
sql_print_error("Read invalid event from master: '%s',\
master could be corrupt but a more likely cause of this is a bug",
errmsg);
my_free((char*)tmp_buf, MYF(MY_ALLOW_ZERO_PTR));
return 1;
}
pthread_mutex_lock(&mi->data_lock);
@ -1978,6 +2086,7 @@ static int queue_old_event(MASTER_INFO *mi, const char *buf,
{
delete ev;
pthread_mutex_unlock(&mi->data_lock);
DBUG_ASSERT(!tmp_buf);
return 1;
}
mi->ignore_stop_event=1;
@ -1986,12 +2095,16 @@ static int queue_old_event(MASTER_INFO *mi, const char *buf,
case STOP_EVENT:
processed_stop_event=1;
break;
case LOAD_EVENT:
// TODO: actually process it
mi->master_log_pos += event_len;
case CREATE_FILE_EVENT:
{
int error = process_io_create_file(mi,(Create_file_log_event*)ev);
delete ev;
mi->master_log_pos += event_len;
pthread_mutex_unlock(&mi->data_lock);
return 0;
DBUG_ASSERT(tmp_buf);
my_free((char*)tmp_buf, MYF(0));
return error;
}
default:
mi->ignore_stop_event=0;
break;
@ -2002,6 +2115,7 @@ static int queue_old_event(MASTER_INFO *mi, const char *buf,
{
delete ev;
pthread_mutex_unlock(&mi->data_lock);
DBUG_ASSERT(!tmp_buf);
return 1;
}
}
@ -2011,6 +2125,7 @@ static int queue_old_event(MASTER_INFO *mi, const char *buf,
if (unlikely(processed_stop_event))
mi->ignore_stop_event=1;
pthread_mutex_unlock(&mi->data_lock);
DBUG_ASSERT(!tmp_buf);
return 0;
}
@ -2173,7 +2288,7 @@ static int safe_reconnect(THD* thd, MYSQL* mysql, MASTER_INFO* mi)
int flush_relay_log_info(RELAY_LOG_INFO* rli)
{
IO_CACHE* file = &rli->info_file;
register IO_CACHE* file = &rli->info_file;
char lbuf[22],lbuf1[22];
my_b_seek(file, 0L);
@ -2251,7 +2366,10 @@ Log_event* next_event(RELAY_LOG_INFO* rli)
}
DBUG_ASSERT(my_b_tell(cur_log) >= 4);
DBUG_ASSERT(my_b_tell(cur_log) == rli->relay_log_pos + rli->pending);
if ((ev=Log_event::read_log_event(cur_log,0,rli->mi->old_format)))
/* relay log is always in new format - if the master is 3.23, the
I/O thread will convert the format for us
*/
if ((ev=Log_event::read_log_event(cur_log,0,(bool)0/*new format*/)))
{
DBUG_ASSERT(thd==rli->sql_thd);
if (hot_log)

View file

@ -254,6 +254,8 @@ typedef struct st_master_info
pthread_mutex_t data_lock,run_lock;
pthread_cond_t data_cond,start_cond,stop_cond;
THD *io_thd;
MYSQL* mysql;
uint32 file_id; // for 3.23 load data infile
RELAY_LOG_INFO rli;
uint port;
uint connect_retry;

View file

@ -708,11 +708,11 @@ TABLE *reopen_name_locked_table(THD* thd, TABLE_LIST* table_list)
if (open_unireg_entry(thd, table, db, table_name, table_name, 1) ||
!(table->table_cache_key =memdup_root(&table->mem_root,(char*) key,
key_length)))
{
closefrm(table);
pthread_mutex_unlock(&LOCK_open);
DBUG_RETURN(0);
}
{
closefrm(table);
pthread_mutex_unlock(&LOCK_open);
DBUG_RETURN(0);
}
table->key_length=key_length;
table->version=0;

View file

@ -136,12 +136,12 @@ THD::THD():user_time(0),fatal_error(0),last_insert_id_used(0),
/* Initialize sub structures */
bzero((char*) &mem_root,sizeof(mem_root));
user_connect=(UC *)0;
hash_init(&user_vars, USER_VARS_HASH_SIZE, 0, 0,
(hash_get_key) get_var_key,
(void (*)(void*)) free_var,0);
#ifdef USING_TRANSACTIONS
bzero((char*) &transaction,sizeof(transaction));
user_connect=(UC *)0;
if (opt_using_transactions)
{
if (open_cached_file(&transaction.trans_log,

View file

@ -147,12 +147,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
if (read_file_from_client && (thd->client_capabilities & CLIENT_LOCAL_FILES))
{
char tmp [FN_REFLEN+1],*end;
DBUG_PRINT("info",("reading local file"));
tmp[0] = (char) 251; /* NULL_LENGTH */
end=strnmov(tmp+1,ex->file_name,sizeof(tmp)-2);
(void) my_net_write(&thd->net,tmp,(uint) (end-tmp));
(void) net_flush(&thd->net);
(void)net_request_file(&thd->net,ex->file_name);
file = -1;
}
else

View file

@ -233,8 +233,7 @@ static bool check_user(THD *thd,enum_server_command command, const char *user,
db ? db : (char*) "");
thd->db_access=0;
/* Don't allow user to connect if he has done too many queries */
if ((max_questions || max_user_connections) &&
get_or_create_user_conn(thd,user,thd->host_or_ip,max_questions))
if ((max_questions || max_user_connections) && get_or_create_user_conn(thd,user,thd->host_or_ip,max_questions))
return -1;
if (max_user_connections && thd->user_connect &&
check_for_max_user_connections(thd->user_connect))

View file

@ -2929,17 +2929,17 @@ return_zero_rows(select_result *result,TABLE_LIST *tables,List<Item> &fields,
if (having && having->val_int() == 0)
send_row=0;
}
if (!tables || !(result->send_fields(fields,1)))
if (!(result->send_fields(fields,1)))
{
if (send_row)
result->send_data(fields);
if (tables) // Not from do_select()
if (tables) // Not from do_select()
{
/* Close open cursors */
for (TABLE_LIST *table=tables; table ; table=table->next)
table->table->file->index_end();
result->send_eof(); // Should be safe
}
result->send_eof(); // Should be safe
}
DBUG_RETURN(0);
}
@ -4877,8 +4877,10 @@ end_send(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
{
JOIN_TAB *jt=join->join_tab;
if ((join->tables == 1) && !join->tmp_table && !join->sort_and_group
&& !join->send_group_parts && !join->having && !jt->select_cond)
&& !join->send_group_parts && !join->having && !jt->select_cond &&
!(jt->table->file->option_flag() & HA_NOT_EXACT_COUNT))
{
/* Join over all rows in table; Return number of found rows */
join->select_options ^= OPTION_FOUND_ROWS;
join->send_records = jt->records;
}
@ -5603,6 +5605,7 @@ create_sort_index(JOIN_TAB *tab,ORDER *order,ha_rows select_limit)
table->file->info(HA_STATUS_VARIABLE); // Get record count
table->found_records=filesort(table,sortorder,length,
select, 0L, select_limit, &examined_rows);
tab->records=table->found_records; // For SQL_CALC_ROWS
delete select; // filesort did select
tab->select=0;
tab->select_cond=0;

View file

@ -911,6 +911,11 @@ static int prepare_for_restore(THD* thd, TABLE_LIST* table)
"Failed generating table from .frm file"));
}
}
// now we should be able to open the partially restored table
// to finish the restore in the handler later on
if (!(table->table = reopen_name_locked_table(thd, table)))
unlock_table_name(thd, table);
DBUG_RETURN(0);
}
@ -919,8 +924,9 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables,
HA_CHECK_OPT* check_opt,
const char *operator_name,
thr_lock_type lock_type,
bool open_for_modify, bool restore,
bool open_for_modify,
uint extra_open_options,
int (*prepare_func)(THD *, TABLE_LIST *),
int (handler::*operator_func)
(THD *, HA_CHECK_OPT *))
{
@ -952,18 +958,13 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables,
table->table = open_ltable(thd, table, lock_type);
thd->open_options&= ~extra_open_options;
packet->length(0);
if (restore)
if (prepare_func)
{
switch (prepare_for_restore(thd, table)) {
case 1: continue; // error, message written to net
case -1: goto err; // error, message could be written to net
default: ;// should be 0 otherwise
switch ((*prepare_func)(thd, table)) {
case 1: continue; // error, message written to net
case -1: goto err; // error, message could be written to net
default: ; // should be 0 otherwise
}
// now we should be able to open the partially restored table
// to finish the restore in the handler later on
if (!(table->table = reopen_name_locked_table(thd, table)))
unlock_table_name(thd, table);
}
if (!table->table)
@ -1096,7 +1097,8 @@ int mysql_restore_table(THD* thd, TABLE_LIST* table_list)
{
DBUG_ENTER("mysql_restore_table");
DBUG_RETURN(mysql_admin_table(thd, table_list, 0,
"restore", TL_WRITE, 1, 1,0,
"restore", TL_WRITE, 1, 0,
&prepare_for_restore,
&handler::restore));
}
@ -1104,7 +1106,7 @@ int mysql_repair_table(THD* thd, TABLE_LIST* tables, HA_CHECK_OPT* check_opt)
{
DBUG_ENTER("mysql_repair_table");
DBUG_RETURN(mysql_admin_table(thd, tables, check_opt,
"repair", TL_WRITE, 1, 0, HA_OPEN_FOR_REPAIR,
"repair", TL_WRITE, 1, HA_OPEN_FOR_REPAIR, 0,
&handler::repair));
}
@ -1143,7 +1145,7 @@ int mysql_check_table(THD* thd, TABLE_LIST* tables,HA_CHECK_OPT* check_opt)
DBUG_ENTER("mysql_check_table");
DBUG_RETURN(mysql_admin_table(thd, tables, check_opt,
"check", lock_type,
0, 0, HA_OPEN_FOR_REPAIR,
0, HA_OPEN_FOR_REPAIR, 0,
&handler::check));
}
@ -1157,7 +1159,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
ORDER *order,
bool drop_primary,
enum enum_duplicates handle_duplicates,
enum enum_enable_or_disable keys_onoff,
enum enum_enable_or_disable keys_onoff,
bool simple_alter)
{
TABLE *table,*new_table;

View file

@ -4,7 +4,7 @@
# MySQL.
#
# You can copy this file to
# /etc/mf.cnf to set global options,
# /etc/my.cnf to set global options,
# mysql-data-dir/my.cnf to set server-specific options (in this
# installation this directory is @localstatedir@) or
# ~/.my.cnf to set user-specific options.

View file

@ -4,7 +4,7 @@
# MySQL.
#
# You can copy this file to
# /etc/mf.cnf to set global options,
# /etc/my.cnf to set global options,
# mysql-data-dir/my.cnf to set server-specific options (in this
# installation this directory is @localstatedir@) or
# ~/.my.cnf to set user-specific options.

View file

@ -5,7 +5,7 @@
# other programs (like a web server)
#
# You can copy this file to
# /etc/mf.cnf to set global options,
# /etc/my.cnf to set global options,
# mysql-data-dir/my.cnf to set server-specific options (in this
# installation this directory is @localstatedir@) or
# ~/.my.cnf to set user-specific options.

View file

@ -5,7 +5,7 @@
# doesn't use much resources.
#
# You can copy this file to
# /etc/mf.cnf to set global options,
# /etc/my.cnf to set global options,
# mysql-data-dir/my.cnf to set server-specific options (in this
# installation this directory is @localstatedir@) or
# ~/.my.cnf to set user-specific options.