mirror of
https://github.com/percona/percona-toolkit.git
synced 2025-09-12 14:18:32 +00:00
Make TableParser.pm handle ANSI quotes
This commit is contained in:
@@ -129,9 +129,15 @@ sub parse {
|
|||||||
my ( $self, $ddl, $opts ) = @_;
|
my ( $self, $ddl, $opts ) = @_;
|
||||||
return unless $ddl;
|
return unless $ddl;
|
||||||
|
|
||||||
if ( $ddl !~ m/CREATE (?:TEMPORARY )?TABLE `/ ) {
|
# If ANSI_QUOTES is enabled, we can't parse. But we can translate ANSI_QUOTES
|
||||||
die "Cannot parse table definition; is ANSI quoting "
|
# into legacy quoting with backticks. The rules are: an identifier is
|
||||||
. "enabled or SQL_QUOTE_SHOW_CREATE disabled?";
|
# surrounded with the quote characters, and embedded quote characters are
|
||||||
|
# doubled.
|
||||||
|
if ( $ddl =~ m/CREATE (?:TEMPORARY )?TABLE "/ ) {
|
||||||
|
$ddl = $self->ansi_to_legacy($ddl);
|
||||||
|
}
|
||||||
|
elsif ( $ddl !~ m/CREATE (?:TEMPORARY )?TABLE `/ ) {
|
||||||
|
die "TableParser doesn't handle CREATE TABLE without quoting.";
|
||||||
}
|
}
|
||||||
|
|
||||||
my ($name) = $ddl =~ m/CREATE (?:TEMPORARY )?TABLE\s+(`.+?`)/;
|
my ($name) = $ddl =~ m/CREATE (?:TEMPORARY )?TABLE\s+(`.+?`)/;
|
||||||
@@ -535,6 +541,28 @@ sub get_table_status {
|
|||||||
return @tables;
|
return @tables;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Translates ANSI quoting around SHOW CREATE TABLE (specifically this query's
|
||||||
|
# output, not an arbitrary query) into legacy backtick-quoting.
|
||||||
|
# DOESNT WORK: my $ansi_quote_re = qr/"(?:(?!(?<!")").)*"/;
|
||||||
|
# DOESNT WORK: my $ansi_quote_re = qr/" [^\\"]* (?: (?:\\.|"") [^\\"]* )* "/ismx;
|
||||||
|
my $ansi_quote_re = qr/" [^"]* (?: "" [^"]* )* (?<=.) "/ismx;
|
||||||
|
sub ansi_to_legacy {
|
||||||
|
my ($self, $ddl) = @_;
|
||||||
|
$ddl =~ s/($ansi_quote_re)/ansi_quote_replace($1)/ge;
|
||||||
|
return $ddl;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Translates a single string from ANSI quoting into legacy quoting by
|
||||||
|
# un-doubling embedded double-double quotes, doubling backticks, and replacing
|
||||||
|
# the delimiters.
|
||||||
|
sub ansi_quote_replace {
|
||||||
|
my ($val) = @_;
|
||||||
|
$val =~ s/^"|"$//g;
|
||||||
|
$val =~ s/`/``/g;
|
||||||
|
$val =~ s/""/"/g;
|
||||||
|
return "`$val`";
|
||||||
|
}
|
||||||
|
|
||||||
sub _d {
|
sub _d {
|
||||||
my ($package, undef, $line) = caller 0;
|
my ($package, undef, $line) = caller 0;
|
||||||
@_ = map { (my $temp = $_) =~ s/\n/\n# /g; $temp; }
|
@_ = map { (my $temp = $_) =~ s/\n/\n# /g; $temp; }
|
||||||
|
@@ -39,6 +39,10 @@ SKIP: {
|
|||||||
);
|
);
|
||||||
|
|
||||||
my $ddl = $tp->get_create_table($dbh, 'sakila', 'actor');
|
my $ddl = $tp->get_create_table($dbh, 'sakila', 'actor');
|
||||||
|
if ( $ddl =~ m/TABLE "actor"/ ) { # It's ANSI quoting, compensate
|
||||||
|
$ddl = $tp->ansi_to_legacy($ddl);
|
||||||
|
$ddl = "$ddl ENGINE=InnoDB AUTO_INCREMENT=201 DEFAULT CHARSET=utf8";
|
||||||
|
}
|
||||||
ok(
|
ok(
|
||||||
no_diff(
|
no_diff(
|
||||||
"$ddl\n",
|
"$ddl\n",
|
||||||
@@ -54,7 +58,7 @@ SKIP: {
|
|||||||
$ddl = $tp->get_create_table($dbh, qw(test t));
|
$ddl = $tp->get_create_table($dbh, qw(test t));
|
||||||
like(
|
like(
|
||||||
$ddl,
|
$ddl,
|
||||||
qr/`a b`\s+/,
|
qr/[`"]a b[`"]\s+/,
|
||||||
"Does not compress spaces (bug 932442)"
|
"Does not compress spaces (bug 932442)"
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@@ -64,11 +68,6 @@ eval {
|
|||||||
};
|
};
|
||||||
like($EVAL_ERROR, qr/quoting/, 'No quoting');
|
like($EVAL_ERROR, qr/quoting/, 'No quoting');
|
||||||
|
|
||||||
eval {
|
|
||||||
$tp->parse( load_file('t/lib/samples/ansi_quotes.sql') );
|
|
||||||
};
|
|
||||||
like($EVAL_ERROR, qr/quoting/, 'ANSI quoting');
|
|
||||||
|
|
||||||
$tbl = $tp->parse( load_file('t/lib/samples/t1.sql') );
|
$tbl = $tp->parse( load_file('t/lib/samples/t1.sql') );
|
||||||
is_deeply(
|
is_deeply(
|
||||||
$tbl,
|
$tbl,
|
||||||
@@ -146,6 +145,21 @@ is_deeply(
|
|||||||
'Indexes with prefixes parse OK (fixes issue 1)'
|
'Indexes with prefixes parse OK (fixes issue 1)'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
is(
|
||||||
|
$tp->ansi_to_legacy( load_file('t/lib/samples/ansi.quoting.sql') ),
|
||||||
|
q{CREATE TABLE `t` (
|
||||||
|
`a` int(11) DEFAULT NULL,
|
||||||
|
`b``c` int(11) DEFAULT NULL,
|
||||||
|
`d"e` int(11) DEFAULT NULL,
|
||||||
|
`f
|
||||||
|
g` int(11) DEFAULT NULL,
|
||||||
|
`h\` int(11) DEFAULT NULL,
|
||||||
|
`i\"` int(11) DEFAULT NULL
|
||||||
|
)
|
||||||
|
},
|
||||||
|
'ANSI quotes (with all kinds of dumb things) get translated correctly'
|
||||||
|
);
|
||||||
|
|
||||||
$tbl = $tp->parse( load_file('t/lib/samples/sakila.film.sql') );
|
$tbl = $tp->parse( load_file('t/lib/samples/sakila.film.sql') );
|
||||||
is_deeply(
|
is_deeply(
|
||||||
$tbl,
|
$tbl,
|
||||||
|
9
t/lib/samples/ansi.quoting.sql
Normal file
9
t/lib/samples/ansi.quoting.sql
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
CREATE TABLE "t" (
|
||||||
|
"a" int(11) DEFAULT NULL,
|
||||||
|
"b`c" int(11) DEFAULT NULL,
|
||||||
|
"d""e" int(11) DEFAULT NULL,
|
||||||
|
"f
|
||||||
|
g" int(11) DEFAULT NULL,
|
||||||
|
"h\" int(11) DEFAULT NULL,
|
||||||
|
"i\""" int(11) DEFAULT NULL
|
||||||
|
)
|
Reference in New Issue
Block a user