mirror of
https://github.com/MariaDB/server.git
synced 2026-10-23 18:49:29 +03:00
PQ: add mtr --ignore-parallel-diff
Parallel query execution appends _parallel to the 'type' column of
tabular EXPLAIN/ANALYZE, so an existing test whose plan gets
parallelized fails on that one column alone:
-17 DERIVED r1 ALL NULL NULL NULL NULL 2
+17 DERIVED r1 ALL_parallel NULL NULL NULL NULL 2
Running the whole suite with --parallel-worker-threads > 0 then buries
the failures that are worth looking at.
Add --ignore-parallel-diff, which makes the result comparison ignore
that suffix: once the two files are known to differ, strip the
suffix from both and compare again.
The text has to be exactly one of ALL, range or index followed
by _parallel, and it has to fill the span between two field
delimiters ('\t', '\n', or end of file).
FORMAT=JSON does not match this criteria, so is not affected.
This commit is contained in:
committed by
Rex Johnston
parent
df939fc32a
commit
bbdeefd981
@@ -207,6 +207,9 @@ static char TMPDIR[FN_REFLEN];
|
||||
static char global_subst_from[200];
|
||||
static char global_subst_to[200];
|
||||
static char *global_subst= NULL;
|
||||
static my_bool opt_ignore_parallel_diff= 0;
|
||||
/* Set once --ignore-parallel-diff has actually had to rewrite something. */
|
||||
static my_bool ignored_parallel_diff= 0;
|
||||
static char *read_command_buf= NULL;
|
||||
static MEM_ROOT require_file_root;
|
||||
static const my_bool my_true= 1;
|
||||
@@ -2491,6 +2494,84 @@ enum compare_files_result_enum {
|
||||
RESULT_LENGTH_MISMATCH= 2
|
||||
};
|
||||
|
||||
/*
|
||||
The access types the parallel suffix can be attached to. The server appends
|
||||
"_parallel" to join_type_str[type] for a table the workers read, see
|
||||
Explain_table_access::print_explain().
|
||||
Currently, only 3 types of access are supported but when others get
|
||||
parallelized, they should be added here too
|
||||
*/
|
||||
static const char *parallel_access_types[]= { "ALL", "range", "index", NULL };
|
||||
|
||||
/*
|
||||
Remove the "_parallel" suffix from tabular EXPLAIN/ANALYZE 'type' values, so
|
||||
that a result recorded without parallel query execution compares equal to one
|
||||
produced with it. For --ignore-parallel-diff.
|
||||
|
||||
Only a whole field is rewritten: the text has to be exactly one of
|
||||
parallel_access_types[] followed by the suffix, filling the span between two
|
||||
field delimiters. A row is written as values separated by '\t' and terminated
|
||||
by '\n' (with --vertical_results, as "name\tvalue\n"), so those two bound the
|
||||
field. That is also what keeps FORMAT=JSON out of it: there the value is
|
||||
quoted, so the suffix is followed by '"' and never by a delimiter.
|
||||
|
||||
ds is the raw content of a file and is not NUL terminated, so every read here
|
||||
is bounded by ds->length.
|
||||
|
||||
@return how many suffixes were removed.
|
||||
*/
|
||||
static size_t strip_parallel_suffix(DYNAMIC_STRING *ds)
|
||||
{
|
||||
static const char suffix[]= "_parallel";
|
||||
const size_t suffix_len= sizeof(suffix) - 1;
|
||||
char *str= ds->str;
|
||||
size_t pos= 0, removed= 0;
|
||||
|
||||
while (ds->length >= suffix_len && pos <= ds->length - suffix_len)
|
||||
{
|
||||
if (memcmp(str + pos, suffix, suffix_len))
|
||||
{
|
||||
pos++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* The suffix has to end the field: a delimiter, or the end of the file. */
|
||||
const size_t end= pos + suffix_len;
|
||||
if (end < ds->length && str[end] != '\t' && str[end] != '\n')
|
||||
{
|
||||
pos++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Back to the start of the field. */
|
||||
size_t start= pos;
|
||||
while (start > 0 && str[start - 1] != '\t' && str[start - 1] != '\n')
|
||||
start--;
|
||||
|
||||
/* What the field holds before the suffix has to be an access type, alone. */
|
||||
const size_t name_len= pos - start;
|
||||
uint i;
|
||||
for (i= 0; parallel_access_types[i]; i++)
|
||||
{
|
||||
const char *name= parallel_access_types[i];
|
||||
if (strlen(name) == name_len && !memcmp(str + start, name, name_len))
|
||||
break;
|
||||
}
|
||||
if (!parallel_access_types[i])
|
||||
{
|
||||
pos++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Drop the suffix. pos then holds the delimiter, nothing to rescan. */
|
||||
memmove(str + pos, str + end, ds->length - end);
|
||||
ds->length-= suffix_len;
|
||||
removed++;
|
||||
}
|
||||
|
||||
return removed;
|
||||
}
|
||||
|
||||
/*
|
||||
Compare two files, given a fd to the first file and
|
||||
name of the second file
|
||||
@@ -2535,6 +2616,21 @@ int compare_files2(File fd1, const char* filename2)
|
||||
if (my_read(fd2, (uchar*) fd2_result.str, fd2_length, MYF(MY_WME | MY_NABP)))
|
||||
die("Error when reading data from result file");
|
||||
|
||||
if (opt_ignore_parallel_diff &&
|
||||
(fd1_result.length != fd2_result.length ||
|
||||
memcmp(fd1_result.str, fd2_result.str, fd1_result.length)))
|
||||
{
|
||||
/*
|
||||
Both sides, so that it does not matter which of the two was recorded
|
||||
with parallel execution on. Only once the files already differ: a run
|
||||
that matches pays nothing for this.
|
||||
*/
|
||||
const size_t stripped1= strip_parallel_suffix(&fd1_result);
|
||||
const size_t stripped2= strip_parallel_suffix(&fd2_result);
|
||||
if (stripped1 || stripped2)
|
||||
ignored_parallel_diff= TRUE;
|
||||
}
|
||||
|
||||
if (global_subst &&
|
||||
(fd1_length != fd2_length ||
|
||||
memcmp(fd1_result.str, fd2_result.str, fd1_length)))
|
||||
@@ -2671,6 +2767,10 @@ int check_result()
|
||||
case RESULT_OK:
|
||||
if (!error_count)
|
||||
{
|
||||
if (ignored_parallel_diff)
|
||||
fprintf(stderr, "Note: '%s' matched only after ignoring the "
|
||||
"'_parallel' EXPLAIN suffix (--ignore-parallel-diff)\n",
|
||||
result_file_name);
|
||||
error= 0;
|
||||
break; /* ok */
|
||||
}
|
||||
@@ -10231,6 +10331,14 @@ static struct my_option my_long_options[] =
|
||||
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
|
||||
{"prologue", 0, "Include SQL before each test case.", &opt_prologue,
|
||||
&opt_prologue, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
|
||||
{"ignore-parallel-diff", 0,
|
||||
"Do not fail on tabular EXPLAIN/ANALYZE differences caused by parallel "
|
||||
"query execution: the '_parallel' suffix on the 'type' column is ignored "
|
||||
"on both sides of the comparison. A development aid for running existing "
|
||||
"tests with parallel execution on; it can hide a real plan change, so it "
|
||||
"cannot be combined with --record.",
|
||||
&opt_ignore_parallel_diff, &opt_ignore_parallel_diff, 0,
|
||||
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
|
||||
{"logdir", OPT_LOG_DIR, "Directory for log files", &opt_logdir,
|
||||
&opt_logdir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
|
||||
{"mark-progress", 0,
|
||||
|
||||
@@ -294,6 +294,7 @@ my $opt_port_base= $ENV{'MTR_PORT_BASE'} || "auto";
|
||||
my $build_thread= 0;
|
||||
|
||||
my $opt_record;
|
||||
my $opt_ignore_parallel_diff;
|
||||
|
||||
our $opt_resfile= $ENV{'MTR_RESULT_FILE'} || 0;
|
||||
|
||||
@@ -1207,6 +1208,7 @@ sub command_line_setup {
|
||||
|
||||
# Test case authoring
|
||||
'record' => \$opt_record,
|
||||
'ignore-parallel-diff' => \$opt_ignore_parallel_diff,
|
||||
'check-testcases!' => \$opt_check_testcases,
|
||||
'mark-progress' => \$opt_mark_progress,
|
||||
|
||||
@@ -1605,6 +1607,14 @@ sub command_line_setup {
|
||||
$opt_parallel= 1;
|
||||
}
|
||||
|
||||
# Recording under --ignore-parallel-diff would write the '_parallel' suffix
|
||||
# into the .result, which then fails for everyone running without parallel
|
||||
# execution.
|
||||
if ( $opt_record and $opt_ignore_parallel_diff )
|
||||
{
|
||||
mtr_error("--record cannot be combined with --ignore-parallel-diff");
|
||||
}
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# Embedded server flag
|
||||
# --------------------------------------------------------------------------
|
||||
@@ -5824,6 +5834,11 @@ sub start_mysqltest ($) {
|
||||
|
||||
client_debug_arg($args, "mysqltest");
|
||||
|
||||
if ( $opt_ignore_parallel_diff )
|
||||
{
|
||||
mtr_add_arg($args, "--ignore-parallel-diff");
|
||||
}
|
||||
|
||||
if ( $opt_record )
|
||||
{
|
||||
mtr_add_arg($args, "--record");
|
||||
@@ -6043,6 +6058,11 @@ Options that specify ports
|
||||
Options for test case authoring
|
||||
|
||||
record TESTNAME (Re)genereate the result file for TESTNAME
|
||||
ignore-parallel-diff Ignore the '_parallel' suffix that parallel query
|
||||
execution adds to the 'type' column of tabular
|
||||
EXPLAIN/ANALYZE, so that results recorded without it
|
||||
still compare equal. Development aid for running
|
||||
existing tests with --parallel-worker-threads > 0
|
||||
check-testcases Check testcases for sideeffects
|
||||
mark-progress Log line number and elapsed time to <testname>.progress
|
||||
|
||||
|
||||
Reference in New Issue
Block a user