Test and fix space-flattening bug.

This commit is contained in:
Daniel Nichter
2012-02-21 13:22:56 -07:00
parent cb7a7946d8
commit 8e9e8eb7a6
5 changed files with 118 additions and 53 deletions

View File

@@ -1771,41 +1771,43 @@ sub get_create_table {
die "I need a tbl parameter" unless $tbl; die "I need a tbl parameter" unless $tbl;
my $q = $self->{Quoter}; my $q = $self->{Quoter};
my $sql = '/*!40101 SET @OLD_SQL_MODE := @@SQL_MODE, ' my $new_sql_mode
. q{@@SQL_MODE := REPLACE(REPLACE(@@SQL_MODE, 'ANSI_QUOTES', ''), ',,', ','), } = '/*!40101 SET @OLD_SQL_MODE := @@SQL_MODE, '
. '@OLD_QUOTE := @@SQL_QUOTE_SHOW_CREATE, ' . q{@@SQL_MODE := REPLACE(REPLACE(@@SQL_MODE, 'ANSI_QUOTES', ''), ',,', ','), }
. '@@SQL_QUOTE_SHOW_CREATE := 1 */'; . '@OLD_QUOTE := @@SQL_QUOTE_SHOW_CREATE, '
PTDEBUG && _d($sql); . '@@SQL_QUOTE_SHOW_CREATE := 1 */';
eval { $dbh->do($sql); };
my $old_sql_mode = '/*!40101 SET @@SQL_MODE := @OLD_SQL_MODE, '
. '@@SQL_QUOTE_SHOW_CREATE := @OLD_QUOTE */';
PTDEBUG && _d($new_sql_mode);
eval { $dbh->do($new_sql_mode); };
PTDEBUG && $EVAL_ERROR && _d($EVAL_ERROR); PTDEBUG && $EVAL_ERROR && _d($EVAL_ERROR);
$sql = 'USE ' . $q->quote($db); my $use_sql = 'USE ' . $q->quote($db);
PTDEBUG && _d($dbh, $sql); PTDEBUG && _d($dbh, $use_sql);
$dbh->do($sql); $dbh->do($use_sql);
$sql = "SHOW CREATE TABLE " . $q->quote($db, $tbl); my $show_sql = "SHOW CREATE TABLE " . $q->quote($db, $tbl);
PTDEBUG && _d($sql); PTDEBUG && _d($show_sql);
my $href; my $href;
eval { $href = $dbh->selectrow_hashref($sql); }; eval { $href = $dbh->selectrow_hashref($show_sql); };
if ( $EVAL_ERROR ) { if ( $EVAL_ERROR ) {
PTDEBUG && _d($EVAL_ERROR); PTDEBUG && _d($EVAL_ERROR);
PTDEBUG && _d($old_sql_mode);
$dbh->do($old_sql_mode);
return; return;
} }
$sql = '/*!40101 SET @@SQL_MODE := @OLD_SQL_MODE, ' PTDEBUG && _d($old_sql_mode);
. '@@SQL_QUOTE_SHOW_CREATE := @OLD_QUOTE */'; $dbh->do($old_sql_mode);
PTDEBUG && _d($sql);
$dbh->do($sql);
my ($key) = grep { m/create table/i } keys %$href; my ($key) = grep { m/create (?:table|view)/i } keys %$href;
if ( $key ) { if ( !$key ) {
PTDEBUG && _d('This table is a base table'); die "Error: no 'Create Table' or 'Create View' in result set from "
$href->{$key} =~ s/\b[ ]{2,}/ /g; . "$show_sql: " . Dumper($href);
$href->{$key} .= "\n";
}
else {
PTDEBUG && _d('This table is a view');
($key) = grep { m/create view/i } keys %$href;
} }
return $href->{$key}; return $href->{$key};

View File

@@ -58,43 +58,63 @@ sub get_create_table {
die "I need a tbl parameter" unless $tbl; die "I need a tbl parameter" unless $tbl;
my $q = $self->{Quoter}; my $q = $self->{Quoter};
my $sql = '/*!40101 SET @OLD_SQL_MODE := @@SQL_MODE, ' # To ensure a consistent output, we save the current (old) SQL mode,
. q{@@SQL_MODE := REPLACE(REPLACE(@@SQL_MODE, 'ANSI_QUOTES', ''), ',,', ','), } # then set it to the new SQL mode that what we need. When done, even
. '@OLD_QUOTE := @@SQL_QUOTE_SHOW_CREATE, ' # if an error occurs, we restore the old SQL mode.
. '@@SQL_QUOTE_SHOW_CREATE := 1 */'; my $new_sql_mode
PTDEBUG && _d($sql); = '/*!40101 SET @OLD_SQL_MODE := @@SQL_MODE, '
eval { $dbh->do($sql); }; . q{@@SQL_MODE := REPLACE(REPLACE(@@SQL_MODE, 'ANSI_QUOTES', ''), ',,', ','), }
. '@OLD_QUOTE := @@SQL_QUOTE_SHOW_CREATE, '
. '@@SQL_QUOTE_SHOW_CREATE := 1 */';
my $old_sql_mode = '/*!40101 SET @@SQL_MODE := @OLD_SQL_MODE, '
. '@@SQL_QUOTE_SHOW_CREATE := @OLD_QUOTE */';
# Set new SQL mode.
PTDEBUG && _d($new_sql_mode);
eval { $dbh->do($new_sql_mode); };
PTDEBUG && $EVAL_ERROR && _d($EVAL_ERROR); PTDEBUG && $EVAL_ERROR && _d($EVAL_ERROR);
# Must USE the tbl's db because some bug with SHOW CREATE TABLE on a # Must USE the tbl's db because some bug with SHOW CREATE TABLE on a
# view when the current db isn't the view's db causes MySQL to crash. # view when the current db isn't the view's db causes MySQL to crash.
$sql = 'USE ' . $q->quote($db); my $use_sql = 'USE ' . $q->quote($db);
PTDEBUG && _d($dbh, $sql); PTDEBUG && _d($dbh, $use_sql);
$dbh->do($sql); $dbh->do($use_sql);
$sql = "SHOW CREATE TABLE " . $q->quote($db, $tbl); my $show_sql = "SHOW CREATE TABLE " . $q->quote($db, $tbl);
PTDEBUG && _d($sql); PTDEBUG && _d($show_sql);
my $href; my $href;
eval { $href = $dbh->selectrow_hashref($sql); }; eval { $href = $dbh->selectrow_hashref($show_sql); };
if ( $EVAL_ERROR ) { if ( $EVAL_ERROR ) {
# TODO: I think we fail silently for tools which may try to call
# this on temp tables, or don't care if the table goes away. We
# should warn $EVAL_ERROR and require callers to eval us and do
# what they want with the warning.
PTDEBUG && _d($EVAL_ERROR); PTDEBUG && _d($EVAL_ERROR);
# Restore old SQL mode.
PTDEBUG && _d($old_sql_mode);
$dbh->do($old_sql_mode);
return; return;
} }
$sql = '/*!40101 SET @@SQL_MODE := @OLD_SQL_MODE, ' # Restore old SQL mode.
. '@@SQL_QUOTE_SHOW_CREATE := @OLD_QUOTE */'; PTDEBUG && _d($old_sql_mode);
PTDEBUG && _d($sql); $dbh->do($old_sql_mode);
$dbh->do($sql);
my ($key) = grep { m/create table/i } keys %$href; # SHOW CREATE TABLE has at least 2 columns like:
if ( $key ) { # mysql> show create table city\G
PTDEBUG && _d('This table is a base table'); # *************************** 1. row ***************************
$href->{$key} =~ s/\b[ ]{2,}/ /g; # Table: city
$href->{$key} .= "\n"; # Create Table: CREATE TABLE `city` (
} # `city_id` smallint(5) unsigned NOT NULL AUTO_INCREMENT,
else { # ...
PTDEBUG && _d('This table is a view'); # We want the second column.
($key) = grep { m/create view/i } keys %$href; my ($key) = grep { m/create (?:table|view)/i } keys %$href;
if ( !$key ) {
die "Error: no 'Create Table' or 'Create View' in result set from "
. "$show_sql: " . Dumper($href);
} }
return $href->{$key}; return $href->{$key};

View File

@@ -9,7 +9,7 @@ BEGIN {
use strict; use strict;
use warnings FATAL => 'all'; use warnings FATAL => 'all';
use English qw(-no_match_vars); use English qw(-no_match_vars);
use Test::More tests => 38; use Test::More tests => 39;
use TableParser; use TableParser;
use Quoter; use Quoter;
@@ -38,15 +38,26 @@ SKIP: {
"get_create_table(nonexistent table)" "get_create_table(nonexistent table)"
); );
my $ddl = $tp->get_create_table($dbh, 'sakila', 'actor');
ok( ok(
no_diff( no_diff(
$tp->get_create_table($dbh, 'sakila', 'actor'), "$ddl\n",
$sandbox_version ge '5.1' ? "$sample/sakila.actor" $sandbox_version ge '5.1' ? "$sample/sakila.actor"
: "$sample/sakila.actor-5.0", : "$sample/sakila.actor-5.0",
cmd_output => 1, cmd_output => 1,
), ),
"get_create_table(sakila.actor)" "get_create_table(sakila.actor)"
); );
# Bug 932442: column with 2 spaces
$sb->load_file('master', "t/pt-table-checksum/samples/2-space-col.sql");
PerconaTest::wait_for_table($dbh, "test.t");
$ddl = $tp->get_create_table($dbh, qw(test t));
like(
$ddl,
qr/`a b`\s+/,
"Does not compress spaces (bug 932442)"
);
}; };
eval { eval {

View File

@@ -41,7 +41,7 @@ elsif ( !@{$master_dbh->selectall_arrayref('show databases like "sakila"')} ) {
plan skip_all => 'sakila database is not loaded'; plan skip_all => 'sakila database is not loaded';
} }
else { else {
plan tests => 30; plan tests => 32;
} }
# The sandbox servers run with lock_wait_timeout=3 and it's not dynamic # The sandbox servers run with lock_wait_timeout=3 and it's not dynamic
@@ -396,6 +396,30 @@ like(
"--where for upper oob chunk" "--where for upper oob chunk"
); );
# #############################################################################
# Bug 932442: column with 2 spaces
# #############################################################################
$sb->load_file('master', "t/pt-table-checksum/samples/2-space-col.sql");
PerconaTest::wait_for_table($master_dbh, "test.t", "id=10");
$output = output(
sub { $exit_status = pt_table_checksum::main(@args,
qw(-t test.t --chunk-size 3)) },
stderr => 1,
);
is(
$exit_status,
0,
"Bug 932442: 0 exit"
);
is(
PerconaTest::count_checksum_results($output, 'errors'),
0,
"Bug 932442: 0 errors"
);
# ############################################################################# # #############################################################################
# Done. # Done.
# ############################################################################# # #############################################################################

View File

@@ -0,0 +1,8 @@
drop database if exists test;
create database test;
use test;
create table t (
id int auto_increment primary key,
`a b` int not null -- 2 spaces between a and b
);
insert into t values (null, 1),(null, 2),(null, 3),(null, 4),(null, 5),(null, 6),(null, 7),(null, 8),(null, 9),(null, 10);